This is a very nice way to detect pstrcpy() into a malloc()ed string, but
[samba.git] / source / lib / util_str.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-2001
5    Copyright (C) Simo Sorce      2001-2002
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23
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
31 BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
32 {
33         const char *s;
34         BOOL quoted;
35         size_t len=1;
36
37         if (!ptr)
38                 return(False);
39
40         s = *ptr;
41
42         /* default to simple separators */
43         if (!sep)
44                 sep = " \t\n\r";
45
46         /* find the first non sep char */
47         while (*s && strchr_m(sep,*s))
48                 s++;
49         
50         /* nothing left? */
51         if (! *s)
52                 return(False);
53         
54         /* copy over the token */
55         for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
56                 if (*s == '\"') {
57                         quoted = !quoted;
58                 } else {
59                         len++;
60                         *buff++ = *s;
61                 }
62         }
63         
64         *ptr = (*s) ? s+1 : s;  
65         *buff = 0;
66         
67         return(True);
68 }
69
70 /****************************************************************************
71 This is like next_token but is not re-entrant and "remembers" the first 
72 parameter so you can pass NULL. This is useful for user interface code
73 but beware the fact that it is not re-entrant!
74 ****************************************************************************/
75
76 static char *last_ptr=NULL;
77
78 BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
79 {
80         BOOL ret;
81         if (!ptr)
82                 ptr = (const char **)&last_ptr;
83
84         ret = next_token(ptr, buff, sep, bufsize);
85         last_ptr = *ptr;
86         return ret;     
87 }
88
89 static uint16 tmpbuf[sizeof(pstring)];
90
91 void set_first_token(char *ptr)
92 {
93         last_ptr = ptr;
94 }
95
96 /****************************************************************************
97  Convert list of tokens to array; dependent on above routine.
98  Uses last_ptr from above - bit of a hack.
99 ****************************************************************************/
100
101 char **toktocliplist(int *ctok, const char *sep)
102 {
103         char *s=last_ptr;
104         int ictok=0;
105         char **ret, **iret;
106
107         if (!sep)
108                 sep = " \t\n\r";
109
110         while(*s && strchr_m(sep,*s))
111                 s++;
112
113         /* nothing left? */
114         if (!*s)
115                 return(NULL);
116
117         do {
118                 ictok++;
119                 while(*s && (!strchr_m(sep,*s)))
120                         s++;
121                 while(*s && strchr_m(sep,*s))
122                         *s++=0;
123         } while(*s);
124         
125         *ctok=ictok;
126         s=last_ptr;
127         
128         if (!(ret=iret=malloc(ictok*sizeof(char *))))
129                 return NULL;
130         
131         while(ictok--) {    
132                 *iret++=s;
133                 while(*s++)
134                         ;
135                 while(!*s)
136                         s++;
137         }
138
139         return ret;
140 }
141
142 /*******************************************************************
143  Case insensitive string compararison.
144 ********************************************************************/
145
146 int StrCaseCmp(const char *s, const char *t)
147 {
148         pstring buf1, buf2;
149         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
150         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
151         return strcmp(buf1,buf2);
152 }
153
154 /*******************************************************************
155  Case insensitive string compararison, length limited.
156 ********************************************************************/
157
158 int StrnCaseCmp(const char *s, const char *t, size_t n)
159 {
160         pstring buf1, buf2;
161         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
162         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
163         return strncmp(buf1,buf2,n);
164 }
165
166 /*******************************************************************
167  Compare 2 strings.
168 ********************************************************************/
169
170 BOOL strequal(const char *s1, const char *s2)
171 {
172         if (s1 == s2)
173                 return(True);
174         if (!s1 || !s2)
175                 return(False);
176   
177         return(StrCaseCmp(s1,s2)==0);
178 }
179
180 /*******************************************************************
181  Compare 2 strings up to and including the nth char.
182 ******************************************************************/
183
184 BOOL strnequal(const char *s1,const char *s2,size_t n)
185 {
186   if (s1 == s2)
187           return(True);
188   if (!s1 || !s2 || !n)
189           return(False);
190   
191   return(StrnCaseCmp(s1,s2,n)==0);
192 }
193
194 /*******************************************************************
195  Compare 2 strings (case sensitive).
196 ********************************************************************/
197
198 BOOL strcsequal(const char *s1,const char *s2)
199 {
200   if (s1 == s2)
201           return(True);
202   if (!s1 || !s2)
203           return(False);
204   
205   return(strcmp(s1,s2)==0);
206 }
207
208 /***************************************************************************
209 Do a case-insensitive, whitespace-ignoring string compare.
210 ***************************************************************************/
211
212 int strwicmp(const char *psz1, const char *psz2)
213 {
214         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
215         /* appropriate value. */
216         if (psz1 == psz2)
217                 return (0);
218         else if (psz1 == NULL)
219                 return (-1);
220         else if (psz2 == NULL)
221                 return (1);
222
223         /* sync the strings on first non-whitespace */
224         while (1) {
225                 while (isspace((int)*psz1))
226                         psz1++;
227                 while (isspace((int)*psz2))
228                         psz2++;
229                 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
230                     || *psz2 == '\0')
231                         break;
232                 psz1++;
233                 psz2++;
234         }
235         return (*psz1 - *psz2);
236 }
237
238
239 /*******************************************************************
240  Convert a string to upper case, but don't modify it.
241 ********************************************************************/
242
243 char *strupper_static(const char *s)
244 {
245         static pstring str;
246
247         pstrcpy(str, s);
248         strupper(str);
249
250         return str;
251 }
252
253 /*******************************************************************
254  Convert a string to "normal" form.
255 ********************************************************************/
256
257 void strnorm(char *s)
258 {
259         extern int case_default;
260         if (case_default == CASE_UPPER)
261                 strupper(s);
262         else
263                 strlower(s);
264 }
265
266 /*******************************************************************
267  Check if a string is in "normal" case.
268 ********************************************************************/
269
270 BOOL strisnormal(const char *s)
271 {
272         extern int case_default;
273         if (case_default == CASE_UPPER)
274                 return(!strhaslower(s));
275         
276         return(!strhasupper(s));
277 }
278
279
280 /****************************************************************************
281  String replace.
282  NOTE: oldc and newc must be 7 bit characters
283 ****************************************************************************/
284
285 void string_replace(char *s,char oldc,char newc)
286 {
287         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
288         string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
289         pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
290 }
291
292 /*******************************************************************
293  Skip past some strings in a buffer.
294 ********************************************************************/
295
296 char *skip_string(char *buf,size_t n)
297 {
298         while (n--)
299                 buf += strlen(buf) + 1;
300         return(buf);
301 }
302
303 /*******************************************************************
304  Count the number of characters in a string. Normally this will
305  be the same as the number of bytes in a string for single byte strings,
306  but will be different for multibyte.
307 ********************************************************************/
308
309 size_t str_charnum(const char *s)
310 {
311         uint16 tmpbuf2[sizeof(pstring)];
312         push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
313         return strlen_w(tmpbuf2);
314 }
315
316 /*******************************************************************
317  Count the number of characters in a string. Normally this will
318  be the same as the number of bytes in a string for single byte strings,
319  but will be different for multibyte.
320 ********************************************************************/
321
322 size_t str_ascii_charnum(const char *s)
323 {
324         pstring tmpbuf2;
325         push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
326         return strlen(tmpbuf2);
327 }
328
329 /*******************************************************************
330  Trim the specified elements off the front and back of a string.
331 ********************************************************************/
332
333 BOOL trim_string(char *s,const char *front,const char *back)
334 {
335         BOOL ret = False;
336         size_t front_len;
337         size_t back_len;
338         size_t len;
339
340         /* Ignore null or empty strings. */
341         if (!s || (s[0] == '\0'))
342                 return False;
343
344         front_len       = front? strlen(front) : 0;
345         back_len        = back? strlen(back) : 0;
346
347         len = strlen(s);
348
349         if (front_len) {
350                 while (len && strncmp(s, front, front_len)==0) {
351                         memcpy(s, s+front_len, (len-front_len)+1);
352                         len -= front_len;
353                         ret=True;
354                 }
355         }
356         
357         if (back_len) {
358                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
359                         s[len-back_len]='\0';
360                         len -= back_len;
361                         ret=True;
362                 }
363         }
364         return ret;
365 }
366
367 /****************************************************************************
368  Does a string have any uppercase chars in it?
369 ****************************************************************************/
370
371 BOOL strhasupper(const char *s)
372 {
373         smb_ucs2_t *ptr;
374         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
375         for(ptr=tmpbuf;*ptr;ptr++)
376                 if(isupper_w(*ptr))
377                         return True;
378         return(False);
379 }
380
381 /****************************************************************************
382  Does a string have any lowercase chars in it?
383 ****************************************************************************/
384
385 BOOL strhaslower(const char *s)
386 {
387         smb_ucs2_t *ptr;
388         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
389         for(ptr=tmpbuf;*ptr;ptr++)
390                 if(islower_w(*ptr))
391                         return True;
392         return(False);
393 }
394
395 /****************************************************************************
396  Find the number of 'c' chars in a string
397 ****************************************************************************/
398
399 size_t count_chars(const char *s,char c)
400 {
401         smb_ucs2_t *ptr;
402         int count;
403         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
404         for(count=0,ptr=tmpbuf;*ptr;ptr++)
405                 if(*ptr==UCS2_CHAR(c))
406                         count++;
407         return(count);
408 }
409
410 /*******************************************************************
411 Return True if a string consists only of one particular character.
412 ********************************************************************/
413
414 BOOL str_is_all(const char *s,char c)
415 {
416         smb_ucs2_t *ptr;
417
418         if(s == NULL)
419                 return False;
420         if(!*s)
421                 return False;
422   
423         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
424         for(ptr=tmpbuf;*ptr;ptr++)
425                 if(*ptr!=UCS2_CHAR(c))
426                         return False;
427
428         return True;
429 }
430
431 /*******************************************************************
432  Safe string copy into a known length string. maxlength does not
433  include the terminating zero.
434 ********************************************************************/
435
436 char *safe_strcpy(char *dest,const char *src, size_t maxlength)
437 {
438         size_t len;
439
440         if (!dest) {
441                 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
442                 return NULL;
443         }
444
445 #ifdef DEVELOPER
446         dest[maxlength]='\0';
447 #endif
448
449         if (!src) {
450                 *dest = 0;
451                 return dest;
452         }  
453
454         len = strlen(src);
455
456         if (len > maxlength) {
457                 DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
458                          (unsigned int)(len-maxlength), len, maxlength, src));
459                 len = maxlength;
460         }
461       
462         memmove(dest, src, len);
463         dest[len] = 0;
464         return dest;
465 }  
466
467 /*******************************************************************
468  Safe string cat into a string. maxlength does not
469  include the terminating zero.
470 ********************************************************************/
471
472 char *safe_strcat(char *dest, const char *src, size_t maxlength)
473 {
474         size_t src_len, dest_len;
475
476         if (!dest) {
477                 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
478                 return NULL;
479         }
480
481         if (!src)
482                 return dest;
483         
484         src_len = strlen(src);
485         dest_len = strlen(dest);
486
487         if (src_len + dest_len > maxlength) {
488                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
489                          (int)(src_len + dest_len - maxlength), src));
490                 if (maxlength > dest_len) {
491                         memcpy(&dest[dest_len], src, maxlength - dest_len);
492                 }
493                 dest[maxlength] = 0;
494                 return NULL;
495         }
496         
497         memcpy(&dest[dest_len], src, src_len);
498         dest[dest_len + src_len] = 0;
499         return dest;
500 }
501
502 /*******************************************************************
503  Paranoid strcpy into a buffer of given length (includes terminating
504  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
505  and replaces with '_'. Deliberately does *NOT* check for multibyte
506  characters. Don't change it !
507 ********************************************************************/
508
509 char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
510 {
511         size_t len, i;
512
513         if (!dest) {
514                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
515                 return NULL;
516         }
517
518         if (!src) {
519                 *dest = 0;
520                 return dest;
521         }  
522
523         len = strlen(src);
524         if (len >= maxlength)
525                 len = maxlength - 1;
526
527         if (!other_safe_chars)
528                 other_safe_chars = "";
529
530         for(i = 0; i < len; i++) {
531                 int val = (src[i] & 0xff);
532                 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
533                         dest[i] = src[i];
534                 else
535                         dest[i] = '_';
536         }
537
538         dest[i] = '\0';
539
540         return dest;
541 }
542
543 /****************************************************************************
544  Like strncpy but always null terminates. Make sure there is room!
545  The variable n should always be one less than the available size.
546 ****************************************************************************/
547
548 char *StrnCpy(char *dest,const char *src,size_t n)
549 {
550         char *d = dest;
551         if (!dest)
552                 return(NULL);
553         if (!src) {
554                 *dest = 0;
555                 return(dest);
556         }
557         while (n-- && (*d++ = *src++))
558                 ;
559         *d = 0;
560         return(dest);
561 }
562
563 /****************************************************************************
564  Like strncpy but copies up to the character marker.  always null terminates.
565  returns a pointer to the character marker in the source string (src).
566 ****************************************************************************/
567
568 char *strncpyn(char *dest, const char *src, size_t n, char c)
569 {
570         char *p;
571         size_t str_len;
572
573         p = strchr_m(src, c);
574         if (p == NULL) {
575                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
576                 return NULL;
577         }
578
579         str_len = PTR_DIFF(p, src);
580         strncpy(dest, src, MIN(n, str_len));
581         dest[str_len] = '\0';
582
583         return p;
584 }
585
586 /*************************************************************
587  Routine to get hex characters and turn them into a 16 byte array.
588  the array can be variable length, and any non-hex-numeric
589  characters are skipped.  "0xnn" or "0Xnn" is specially catered
590  for.
591
592  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
593
594 **************************************************************/
595
596 size_t strhex_to_str(char *p, size_t len, const char *strhex)
597 {
598         size_t i;
599         size_t num_chars = 0;
600         unsigned char   lonybble, hinybble;
601         const char     *hexchars = "0123456789ABCDEF";
602         char           *p1 = NULL, *p2 = NULL;
603
604         for (i = 0; i < len && strhex[i] != 0; i++) {
605                 if (strnequal(hexchars, "0x", 2)) {
606                         i++; /* skip two chars */
607                         continue;
608                 }
609
610                 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
611                         break;
612
613                 i++; /* next hex digit */
614
615                 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
616                         break;
617
618                 /* get the two nybbles */
619                 hinybble = PTR_DIFF(p1, hexchars);
620                 lonybble = PTR_DIFF(p2, hexchars);
621
622                 p[num_chars] = (hinybble << 4) | lonybble;
623                 num_chars++;
624
625                 p1 = NULL;
626                 p2 = NULL;
627         }
628         return num_chars;
629 }
630
631 /****************************************************************************
632  Check if a string is part of a list.
633 ****************************************************************************/
634
635 BOOL in_list(char *s,char *list,BOOL casesensitive)
636 {
637         pstring tok;
638         const char *p=list;
639
640         if (!list)
641                 return(False);
642
643         while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
644                 if (casesensitive) {
645                         if (strcmp(tok,s) == 0)
646                                 return(True);
647                 } else {
648                         if (StrCaseCmp(tok,s) == 0)
649                                 return(True);
650                 }
651         }
652         return(False);
653 }
654
655 /* this is used to prevent lots of mallocs of size 1 */
656 static char *null_string = NULL;
657
658 /****************************************************************************
659  Set a string value, allocing the space for the string
660 ****************************************************************************/
661
662 static BOOL string_init(char **dest,const char *src)
663 {
664         size_t l;
665         if (!src)     
666                 src = "";
667
668         l = strlen(src);
669
670         if (l == 0) {
671                 if (!null_string) {
672                         if((null_string = (char *)malloc(1)) == NULL) {
673                                 DEBUG(0,("string_init: malloc fail for null_string.\n"));
674                                 return False;
675                         }
676                         *null_string = 0;
677                 }
678                 *dest = null_string;
679         } else {
680                 (*dest) = strdup(src);
681                 if ((*dest) == NULL) {
682                         DEBUG(0,("Out of memory in string_init\n"));
683                         return False;
684                 }
685         }
686         return(True);
687 }
688
689 /****************************************************************************
690  Free a string value.
691 ****************************************************************************/
692
693 void string_free(char **s)
694 {
695         if (!s || !(*s))
696                 return;
697         if (*s == null_string)
698                 *s = NULL;
699         SAFE_FREE(*s);
700 }
701
702 /****************************************************************************
703  Set a string value, deallocating any existing space, and allocing the space
704  for the string
705 ****************************************************************************/
706
707 BOOL string_set(char **dest,const char *src)
708 {
709         string_free(dest);
710         return(string_init(dest,src));
711 }
712
713 /****************************************************************************
714  Substitute a string for a pattern in another string. Make sure there is 
715  enough room!
716
717  This routine looks for pattern in s and replaces it with 
718  insert. It may do multiple replacements.
719
720  Any of " ; ' $ or ` in the insert string are replaced with _
721  if len==0 then the string cannot be extended. This is different from the old
722  use of len==0 which was for no length checks to be done.
723 ****************************************************************************/
724
725 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
726 {
727         char *p;
728         ssize_t ls,lp,li, i;
729
730         if (!insert || !pattern || !*pattern || !s)
731                 return;
732
733         ls = (ssize_t)strlen(s);
734         lp = (ssize_t)strlen(pattern);
735         li = (ssize_t)strlen(insert);
736
737         if (len == 0)
738                 len = ls + 1; /* len is number of *bytes* */
739
740         while (lp <= ls && (p = strstr(s,pattern))) {
741                 if (ls + (li-lp) >= len) {
742                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
743                                  (int)(ls + (li-lp) - len),
744                                  pattern, (int)len));
745                         break;
746                 }
747                 if (li != lp) {
748                         memmove(p+li,p+lp,strlen(p+lp)+1);
749                 }
750                 for (i=0;i<li;i++) {
751                         switch (insert[i]) {
752                         case '`':
753                         case '"':
754                         case '\'':
755                         case ';':
756                         case '$':
757                         case '%':
758                         case '\r':
759                         case '\n':
760                                 p[i] = '_';
761                                 break;
762                         default:
763                                 p[i] = insert[i];
764                         }
765                 }
766                 s = p + li;
767                 ls += (li-lp);
768         }
769 }
770
771 void fstring_sub(char *s,const char *pattern,const char *insert)
772 {
773         string_sub(s, pattern, insert, sizeof(fstring));
774 }
775
776 void pstring_sub(char *s,const char *pattern,const char *insert)
777 {
778         string_sub(s, pattern, insert, sizeof(pstring));
779 }
780
781 /****************************************************************************
782  Similar to string_sub, but it will accept only allocated strings
783  and may realloc them so pay attention at what you pass on no
784  pointers inside strings, no pstrings or const may be passed
785  as string.
786 ****************************************************************************/
787
788 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
789 {
790         char *p, *in;
791         char *s;
792         ssize_t ls,lp,li,ld, i;
793
794         if (!insert || !pattern || !*pattern || !string || !*string)
795                 return NULL;
796
797         s = string;
798
799         in = strdup(insert);
800         if (!in) {
801                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
802                 return NULL;
803         }
804         ls = (ssize_t)strlen(s);
805         lp = (ssize_t)strlen(pattern);
806         li = (ssize_t)strlen(insert);
807         ld = li - lp;
808         for (i=0;i<li;i++) {
809                 switch (in[i]) {
810                         case '`':
811                         case '"':
812                         case '\'':
813                         case ';':
814                         case '$':
815                         case '%':
816                         case '\r':
817                         case '\n':
818                                 in[i] = '_';
819                         default:
820                                 /* ok */
821                                 break;
822                 }
823         }
824         
825         while ((p = strstr(s,pattern))) {
826                 if (ld > 0) {
827                         char *t = Realloc(string, ls + ld + 1);
828                         if (!t) {
829                                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
830                                 SAFE_FREE(in);
831                                 return NULL;
832                         }
833                         string = t;
834                         p = t + (p - s);
835                 }
836                 if (li != lp) {
837                         memmove(p+li,p+lp,strlen(p+lp)+1);
838                 }
839                 memcpy(p, in, li);
840                 s = p + li;
841                 ls += ld;
842         }
843         SAFE_FREE(in);
844         return string;
845 }
846
847 /****************************************************************************
848  Similar to string_sub() but allows for any character to be substituted. 
849  Use with caution!
850  if len==0 then the string cannot be extended. This is different from the old
851  use of len==0 which was for no length checks to be done.
852 ****************************************************************************/
853
854 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
855 {
856         char *p;
857         ssize_t ls,lp,li;
858
859         if (!insert || !pattern || !s)
860                 return;
861
862         ls = (ssize_t)strlen(s);
863         lp = (ssize_t)strlen(pattern);
864         li = (ssize_t)strlen(insert);
865
866         if (!*pattern)
867                 return;
868         
869         if (len == 0)
870                 len = ls + 1; /* len is number of *bytes* */
871         
872         while (lp <= ls && (p = strstr(s,pattern))) {
873                 if (ls + (li-lp) >= len) {
874                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
875                                  (int)(ls + (li-lp) - len),
876                                  pattern, (int)len));
877                         break;
878                 }
879                 if (li != lp) {
880                         memmove(p+li,p+lp,strlen(p+lp)+1);
881                 }
882                 memcpy(p, insert, li);
883                 s = p + li;
884                 ls += (li-lp);
885         }
886 }
887
888 /****************************************************************************
889  Similar to all_string_sub but for unicode strings.
890  Return a new allocated unicode string.
891  similar to string_sub() but allows for any character to be substituted.
892  Use with caution!
893 ****************************************************************************/
894
895 smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
896                                 const smb_ucs2_t *insert)
897 {
898         smb_ucs2_t *r, *rp;
899         const smb_ucs2_t *sp;
900         size_t  lr, lp, li, lt;
901
902         if (!insert || !pattern || !*pattern || !s)
903                 return NULL;
904
905         lt = (size_t)strlen_w(s);
906         lp = (size_t)strlen_w(pattern);
907         li = (size_t)strlen_w(insert);
908
909         if (li > lp) {
910                 const smb_ucs2_t *st = s;
911                 int ld = li - lp;
912                 while ((sp = strstr_w(st, pattern))) {
913                         st = sp + lp;
914                         lt += ld;
915                 }
916         }
917
918         r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
919         if (!r) {
920                 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
921                 return NULL;
922         }
923
924         while ((sp = strstr_w(s, pattern))) {
925                 memcpy(rp, s, (sp - s));
926                 rp += ((sp - s) / sizeof(smb_ucs2_t));
927                 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
928                 s = sp + lp;
929                 rp += li;
930         }
931         lr = ((rp - r) / sizeof(smb_ucs2_t));
932         if (lr < lt) {
933                 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
934                 rp += (lt - lr);
935         }
936         *rp = 0;
937
938         return r;
939 }
940
941 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
942                                              const char *insert)
943 {
944         wpstring p, i;
945
946         if (!insert || !pattern || !s)
947                 return NULL;
948         push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
949         push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
950         return all_string_sub_w(s, p, i);
951 }
952
953 /****************************************************************************
954  Splits out the front and back at a separator.
955 ****************************************************************************/
956
957 void split_at_last_component(char *path, char *front, char sep, char *back)
958 {
959         char *p = strrchr_m(path, sep);
960
961         if (p != NULL)
962                 *p = 0;
963
964         if (front != NULL)
965                 pstrcpy(front, path);
966
967         if (p != NULL) {
968                 if (back != NULL)
969                         pstrcpy(back, p+1);
970                 *p = '\\';
971         } else {
972                 if (back != NULL)
973                         back[0] = 0;
974         }
975 }
976
977 /****************************************************************************
978  Write an octal as a string.
979 ****************************************************************************/
980
981 const char *octal_string(int i)
982 {
983         static char ret[64];
984         if (i == -1)
985                 return "-1";
986         slprintf(ret, sizeof(ret)-1, "0%o", i);
987         return ret;
988 }
989
990
991 /****************************************************************************
992  Truncate a string at a specified length.
993 ****************************************************************************/
994
995 char *string_truncate(char *s, int length)
996 {
997         if (s && strlen(s) > length)
998                 s[length] = 0;
999         return s;
1000 }
1001
1002 /****************************************************************************
1003  Strchr and strrchr_m are very hard to do on general multi-byte strings. 
1004  We convert via ucs2 for now.
1005 ****************************************************************************/
1006
1007 char *strchr_m(const char *s, char c)
1008 {
1009         wpstring ws;
1010         pstring s2;
1011         smb_ucs2_t *p;
1012
1013         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1014         p = strchr_w(ws, UCS2_CHAR(c));
1015         if (!p)
1016                 return NULL;
1017         *p = 0;
1018         pull_ucs2_pstring(s2, ws);
1019         return (char *)(s+strlen(s2));
1020 }
1021
1022 char *strrchr_m(const char *s, char c)
1023 {
1024         wpstring ws;
1025         pstring s2;
1026         smb_ucs2_t *p;
1027
1028         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1029         p = strrchr_w(ws, UCS2_CHAR(c));
1030         if (!p)
1031                 return NULL;
1032         *p = 0;
1033         pull_ucs2_pstring(s2, ws);
1034         return (char *)(s+strlen(s2));
1035 }
1036
1037 /*******************************************************************
1038  Convert a string to lower case.
1039 ********************************************************************/
1040
1041 void strlower_m(char *s)
1042 {
1043         /* this is quite a common operation, so we want it to be
1044            fast. We optimise for the ascii case, knowing that all our
1045            supported multi-byte character sets are ascii-compatible
1046            (ie. they match for the first 128 chars) */
1047
1048         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1049                 *s = tolower((unsigned char)*s);
1050                 s++;
1051         }
1052
1053         if (!*s)
1054                 return;
1055
1056         /* I assume that lowercased string takes the same number of bytes
1057          * as source string even in UTF-8 encoding. (VIV) */
1058         unix_strlower(s,strlen(s)+1,s,strlen(s)+1);     
1059 }
1060
1061 /*******************************************************************
1062  Duplicate convert a string to lower case.
1063 ********************************************************************/
1064
1065 char *strdup_lower(const char *s)
1066 {
1067         char *t = strdup(s);
1068         if (t == NULL) {
1069                 DEBUG(0, ("strdup_lower: Out of memory!\n"));
1070                 return NULL;
1071         }
1072         strlower_m(t);
1073         return t;
1074 }
1075
1076 /*******************************************************************
1077  Convert a string to upper case.
1078 ********************************************************************/
1079
1080 void strupper_m(char *s)
1081 {
1082         /* this is quite a common operation, so we want it to be
1083            fast. We optimise for the ascii case, knowing that all our
1084            supported multi-byte character sets are ascii-compatible
1085            (ie. they match for the first 128 chars) */
1086
1087         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1088                 *s = toupper((unsigned char)*s);
1089                 s++;
1090         }
1091
1092         if (!*s)
1093                 return;
1094
1095         /* I assume that lowercased string takes the same number of bytes
1096          * as source string even in multibyte encoding. (VIV) */
1097         unix_strupper(s,strlen(s)+1,s,strlen(s)+1);     
1098 }
1099
1100 /*******************************************************************
1101  Convert a string to upper case.
1102 ********************************************************************/
1103
1104 char *strdup_upper(const char *s)
1105 {
1106         char *t = strdup(s);
1107         if (t == NULL) {
1108                 DEBUG(0, ("strdup_upper: Out of memory!\n"));
1109                 return NULL;
1110         }
1111         strupper_m(t);
1112         return t;
1113 }
1114
1115 /*******************************************************************
1116  Return a RFC2254 binary string representation of a buffer.
1117  Used in LDAP filters.
1118  Caller must free.
1119 ********************************************************************/
1120
1121 char *binary_string(char *buf, int len)
1122 {
1123         char *s;
1124         int i, j;
1125         const char *hex = "0123456789ABCDEF";
1126         s = malloc(len * 3 + 1);
1127         if (!s)
1128                 return NULL;
1129         for (j=i=0;i<len;i++) {
1130                 s[j] = '\\';
1131                 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1132                 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1133                 j += 3;
1134         }
1135         s[j] = 0;
1136         return s;
1137 }
1138
1139 /*******************************************************************
1140  Just a typesafety wrapper for snprintf into a pstring.
1141 ********************************************************************/
1142
1143  int pstr_sprintf(pstring s, const char *fmt, ...)
1144 {
1145         va_list ap;
1146         int ret;
1147
1148         va_start(ap, fmt);
1149         ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1150         va_end(ap);
1151         return ret;
1152 }
1153
1154 /*******************************************************************
1155  Just a typesafety wrapper for snprintf into a fstring.
1156 ********************************************************************/
1157
1158  int fstr_sprintf(fstring s, const char *fmt, ...)
1159 {
1160         va_list ap;
1161         int ret;
1162
1163         va_start(ap, fmt);
1164         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1165         va_end(ap);
1166         return ret;
1167 }
1168
1169 #ifndef HAVE_STRNDUP
1170 /*******************************************************************
1171  Some platforms don't have strndup.
1172 ********************************************************************/
1173
1174  char *strndup(const char *s, size_t n)
1175 {
1176         char *ret;
1177         
1178         n = strnlen(s, n);
1179         ret = malloc(n+1);
1180         if (!ret)
1181                 return NULL;
1182         memcpy(ret, s, n);
1183         ret[n] = 0;
1184
1185         return ret;
1186 }
1187 #endif
1188
1189 #ifndef HAVE_STRNLEN
1190 /*******************************************************************
1191  Some platforms don't have strnlen
1192 ********************************************************************/
1193
1194  size_t strnlen(const char *s, size_t n)
1195 {
1196         int i;
1197         for (i=0; s[i] && i<n; i++)
1198                 /* noop */ ;
1199         return i;
1200 }
1201 #endif
1202
1203 /***********************************************************
1204  List of Strings manipulation functions
1205 ***********************************************************/
1206
1207 #define S_LIST_ABS 16 /* List Allocation Block Size */
1208
1209 char **str_list_make(const char *string, const char *sep)
1210 {
1211         char **list, **rlist;
1212         const char *str;
1213         char *s;
1214         int num, lsize;
1215         pstring tok;
1216         
1217         if (!string || !*string)
1218                 return NULL;
1219         s = strdup(string);
1220         if (!s) {
1221                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1222                 return NULL;
1223         }
1224         if (!sep) sep = LIST_SEP;
1225         
1226         num = lsize = 0;
1227         list = NULL;
1228         
1229         str = s;
1230         while (next_token(&str, tok, sep, sizeof(tok))) {               
1231                 if (num == lsize) {
1232                         lsize += S_LIST_ABS;
1233                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1234                         if (!rlist) {
1235                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1236                                 str_list_free(&list);
1237                                 SAFE_FREE(s);
1238                                 return NULL;
1239                         } else
1240                                 list = rlist;
1241                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1242                 }
1243                 
1244                 list[num] = strdup(tok);
1245                 if (!list[num]) {
1246                         DEBUG(0,("str_list_make: Unable to allocate memory"));
1247                         str_list_free(&list);
1248                         SAFE_FREE(s);
1249                         return NULL;
1250                 }
1251         
1252                 num++;  
1253         }
1254         
1255         SAFE_FREE(s);
1256         return list;
1257 }
1258
1259 BOOL str_list_copy(char ***dest, const char **src)
1260 {
1261         char **list, **rlist;
1262         int num, lsize;
1263         
1264         *dest = NULL;
1265         if (!src)
1266                 return False;
1267         
1268         num = lsize = 0;
1269         list = NULL;
1270                 
1271         while (src[num]) {
1272                 if (num == lsize) {
1273                         lsize += S_LIST_ABS;
1274                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1275                         if (!rlist) {
1276                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1277                                 str_list_free(&list);
1278                                 return False;
1279                         } else
1280                                 list = rlist;
1281                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1282                 }
1283                 
1284                 list[num] = strdup(src[num]);
1285                 if (!list[num]) {
1286                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
1287                         str_list_free(&list);
1288                         return False;
1289                 }
1290
1291                 num++;
1292         }
1293         
1294         *dest = list;
1295         return True;    
1296 }
1297
1298 /***********************************************************
1299  Return true if all the elements of the list match exactly.
1300 ***********************************************************/
1301
1302 BOOL str_list_compare(char **list1, char **list2)
1303 {
1304         int num;
1305         
1306         if (!list1 || !list2)
1307                 return (list1 == list2); 
1308         
1309         for (num = 0; list1[num]; num++) {
1310                 if (!list2[num])
1311                         return False;
1312                 if (!strcsequal(list1[num], list2[num]))
1313                         return False;
1314         }
1315         if (list2[num])
1316                 return False; /* if list2 has more elements than list1 fail */
1317         
1318         return True;
1319 }
1320
1321 void str_list_free(char ***list)
1322 {
1323         char **tlist;
1324         
1325         if (!list || !*list)
1326                 return;
1327         tlist = *list;
1328         for(; *tlist; tlist++)
1329                 SAFE_FREE(*tlist);
1330         SAFE_FREE(*list);
1331 }
1332
1333 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1334 {
1335         char *p, *s, *t;
1336         ssize_t ls, lp, li, ld, i, d;
1337
1338         if (!list)
1339                 return False;
1340         if (!pattern)
1341                 return False;
1342         if (!insert)
1343                 return False;
1344
1345         lp = (ssize_t)strlen(pattern);
1346         li = (ssize_t)strlen(insert);
1347         ld = li -lp;
1348                         
1349         while (*list) {
1350                 s = *list;
1351                 ls = (ssize_t)strlen(s);
1352
1353                 while ((p = strstr(s, pattern))) {
1354                         t = *list;
1355                         d = p -t;
1356                         if (ld) {
1357                                 t = (char *) malloc(ls +ld +1);
1358                                 if (!t) {
1359                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1360                                         return False;
1361                                 }
1362                                 memcpy(t, *list, d);
1363                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1364                                 SAFE_FREE(*list);
1365                                 *list = t;
1366                                 ls += ld;
1367                                 s = t +d +li;
1368                         }
1369                         
1370                         for (i = 0; i < li; i++) {
1371                                 switch (insert[i]) {
1372                                         case '`':
1373                                         case '"':
1374                                         case '\'':
1375                                         case ';':
1376                                         case '$':
1377                                         case '%':
1378                                         case '\r':
1379                                         case '\n':
1380                                                 t[d +i] = '_';
1381                                                 break;
1382                                         default:
1383                                                 t[d +i] = insert[i];
1384                                 }
1385                         }       
1386                 }
1387                 
1388                 list++;
1389         }
1390         
1391         return True;
1392 }
1393
1394
1395 #define IPSTR_LIST_SEP  ","
1396
1397 /**
1398  * Add ip string representation to ipstr list. Used also
1399  * as part of @function ipstr_list_make
1400  *
1401  * @param ipstr_list pointer to string containing ip list;
1402  *        MUST BE already allocated and IS reallocated if necessary
1403  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1404  *        as a result of reallocation)
1405  * @param ip IP address which is to be added to list
1406  * @return pointer to string appended with new ip and possibly
1407  *         reallocated to new length
1408  **/
1409
1410 char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip)
1411 {
1412         char* new_ipstr = NULL;
1413         
1414         /* arguments checking */
1415         if (!ipstr_list || !ip) return NULL;
1416
1417         /* attempt to convert ip to a string and append colon separator to it */
1418         if (*ipstr_list) {
1419                 asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip));
1420                 SAFE_FREE(*ipstr_list);
1421         } else {
1422                 asprintf(&new_ipstr, "%s", inet_ntoa(*ip));
1423         }
1424         *ipstr_list = new_ipstr;
1425         return *ipstr_list;
1426 }
1427
1428
1429 /**
1430  * Allocate and initialise an ipstr list using ip adresses
1431  * passed as arguments.
1432  *
1433  * @param ipstr_list pointer to string meant to be allocated and set
1434  * @param ip_list array of ip addresses to place in the list
1435  * @param ip_count number of addresses stored in ip_list
1436  * @return pointer to allocated ip string
1437  **/
1438  
1439 char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count)
1440 {
1441         int i;
1442         
1443         /* arguments checking */
1444         if (!ip_list && !ipstr_list) return 0;
1445
1446         *ipstr_list = NULL;
1447         
1448         /* process ip addresses given as arguments */
1449         for (i = 0; i < ip_count; i++)
1450                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1451         
1452         return (*ipstr_list);
1453 }
1454
1455
1456 /**
1457  * Parse given ip string list into array of ip addresses
1458  * (as in_addr structures)
1459  *
1460  * @param ipstr ip string list to be parsed 
1461  * @param ip_list pointer to array of ip addresses which is
1462  *        allocated by this function and must be freed by caller
1463  * @return number of succesfully parsed addresses
1464  **/
1465  
1466 int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list)
1467 {
1468         fstring token_str;
1469         int count;
1470
1471         if (!ipstr_list || !ip_list) return 0;
1472         
1473         for (*ip_list = NULL, count = 0;
1474              next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN);
1475              count++) {
1476              
1477                 struct in_addr addr;
1478
1479                 /* convert single token to ip address */
1480                 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1481                         break;
1482                 
1483                 /* prepare place for another in_addr structure */
1484                 *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr));
1485                 if (!*ip_list) return -1;
1486                 
1487                 (*ip_list)[count] = addr;
1488         }
1489         
1490         return count;
1491 }
1492
1493
1494 /**
1495  * Safely free ip string list
1496  *
1497  * @param ipstr_list ip string list to be freed
1498  **/
1499
1500 void ipstr_list_free(char* ipstr_list)
1501 {
1502         SAFE_FREE(ipstr_list);
1503 }
1504
1505
1506 /***********************************************************
1507  Unescape a URL encoded string, in place.
1508 ***********************************************************/
1509
1510 void rfc1738_unescape(char *buf)
1511 {
1512         char *p=buf;
1513
1514         while ((p=strchr_m(p,'+')))
1515                 *p = ' ';
1516
1517         p = buf;
1518
1519         while (p && *p && (p=strchr_m(p,'%'))) {
1520                 int c1 = p[1];
1521                 int c2 = p[2];
1522
1523                 if (c1 >= '0' && c1 <= '9')
1524                         c1 = c1 - '0';
1525                 else if (c1 >= 'A' && c1 <= 'F')
1526                         c1 = 10 + c1 - 'A';
1527                 else if (c1 >= 'a' && c1 <= 'f')
1528                         c1 = 10 + c1 - 'a';
1529                 else {p++; continue;}
1530
1531                 if (c2 >= '0' && c2 <= '9')
1532                         c2 = c2 - '0';
1533                 else if (c2 >= 'A' && c2 <= 'F')
1534                         c2 = 10 + c2 - 'A';
1535                 else if (c2 >= 'a' && c2 <= 'f')
1536                         c2 = 10 + c2 - 'a';
1537                 else {p++; continue;}
1538                         
1539                 *p = (c1<<4) | c2;
1540
1541                 memmove(p+1, p+3, strlen(p+3)+1);
1542                 p++;
1543         }
1544 }
1545
1546 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1547
1548 /***************************************************************************
1549 decode a base64 string into a DATA_BLOB - simple and slow algorithm
1550   ***************************************************************************/
1551 DATA_BLOB base64_decode_data_blob(const char *s)
1552 {
1553         int bit_offset, byte_offset, idx, i, n;
1554         DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1555         unsigned char *d = decoded.data;
1556         char *p;
1557
1558         n=i=0;
1559
1560         while (*s && (p=strchr_m(b64,*s))) {
1561                 idx = (int)(p - b64);
1562                 byte_offset = (i*6)/8;
1563                 bit_offset = (i*6)%8;
1564                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1565                 if (bit_offset < 3) {
1566                         d[byte_offset] |= (idx << (2-bit_offset));
1567                         n = byte_offset+1;
1568                 } else {
1569                         d[byte_offset] |= (idx >> (bit_offset-2));
1570                         d[byte_offset+1] = 0;
1571                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1572                         n = byte_offset+2;
1573                 }
1574                 s++; i++;
1575         }
1576
1577         /* fix up length */
1578         decoded.length = n;
1579         return decoded;
1580 }
1581
1582 /***************************************************************************
1583 decode a base64 string in-place - wrapper for the above
1584 ***************************************************************************/
1585 void base64_decode(char *s)
1586 {
1587         DATA_BLOB decoded = base64_decode_data_blob(s);
1588         memcpy(s, decoded.data, decoded.length);
1589         data_blob_free(&decoded);
1590
1591         /* null terminate */
1592         s[decoded.length] = '\0';
1593 }
1594
1595 /***************************************************************************
1596 encode a base64 string into a malloc()ed string caller to free.
1597
1598 From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
1599 ***************************************************************************/
1600 char * base64_encode_data_blob(DATA_BLOB data)
1601 {
1602         int bits = 0;
1603         int char_count = 0;
1604         size_t out_cnt = 0;
1605         size_t len = data.length;
1606         size_t output_len = data.length * 2;
1607         char *result = malloc(output_len); /* get us plenty of space */
1608
1609         while (len-- && out_cnt < (data.length * 2) - 5) {
1610                 int c = (unsigned char) *(data.data++);
1611                 bits += c;
1612                 char_count++;
1613                 if (char_count == 3) {
1614                         result[out_cnt++] = b64[bits >> 18];
1615                         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1616                         result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1617             result[out_cnt++] = b64[bits & 0x3f];
1618             bits = 0;
1619             char_count = 0;
1620         } else {
1621             bits <<= 8;
1622         }
1623     }
1624     if (char_count != 0) {
1625         bits <<= 16 - (8 * char_count);
1626         result[out_cnt++] = b64[bits >> 18];
1627         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1628         if (char_count == 1) {
1629             result[out_cnt++] = '=';
1630             result[out_cnt++] = '=';
1631         } else {
1632             result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1633             result[out_cnt++] = '=';
1634         }
1635     }
1636     result[out_cnt] = '\0';     /* terminate */
1637     return result;
1638 }
1639
1640 #ifdef VALGRIND
1641 size_t valgrind_strlen(const char *s)
1642 {
1643         size_t count;
1644         for(count = 0; *s++; count++)
1645                 ;
1646         return count;
1647 }
1648 #endif