move to SAFE_FREE()
[samba.git] / source / lib / util_str.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-2001
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 extern int DEBUGLEVEL;
25
26 /****************************************************************************
27   Get the next token from a string, return False if none found
28   handles double-quotes. 
29 Based on a routine by GJC@VILLAGE.COM. 
30 Extensively modified by Andrew.Tridgell@anu.edu.au
31 ****************************************************************************/
32 BOOL next_token(char **ptr,char *buff,char *sep, size_t bufsize)
33 {
34         char *s;
35         BOOL quoted;
36         size_t len=1;
37
38         if (!ptr) return(False);
39
40         s = *ptr;
41
42         /* default to simple separators */
43         if (!sep) sep = " \t\n\r";
44
45         /* find the first non sep char */
46         while (*s && strchr_m(sep,*s)) s++;
47         
48         /* nothing left? */
49         if (! *s) return(False);
50         
51         /* copy over the token */
52         for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
53                 if (*s == '\"') {
54                         quoted = !quoted;
55                 } else {
56                         len++;
57                         *buff++ = *s;
58                 }
59         }
60         
61         *ptr = (*s) ? s+1 : s;  
62         *buff = 0;
63         
64         return(True);
65 }
66
67
68
69 /****************************************************************************
70 This is like next_token but is not re-entrant and "remembers" the first 
71 parameter so you can pass NULL. This is useful for user interface code
72 but beware the fact that it is not re-entrant!
73 ****************************************************************************/
74 static char *last_ptr=NULL;
75
76 BOOL next_token_nr(char **ptr,char *buff,char *sep, size_t bufsize)
77 {
78         BOOL ret;
79         if (!ptr) ptr = &last_ptr;
80
81         ret = next_token(ptr, buff, sep, bufsize);
82         last_ptr = *ptr;
83         return ret;     
84 }
85
86 static uint16 tmpbuf[sizeof(pstring)];
87
88 void set_first_token(char *ptr)
89 {
90         last_ptr = ptr;
91 }
92
93
94 /****************************************************************************
95 Convert list of tokens to array; dependent on above routine.
96 Uses last_ptr from above - bit of a hack.
97 ****************************************************************************/
98 char **toktocliplist(int *ctok, char *sep)
99 {
100         char *s=last_ptr;
101         int ictok=0;
102         char **ret, **iret;
103
104         if (!sep) sep = " \t\n\r";
105
106         while(*s && strchr_m(sep,*s)) s++;
107
108         /* nothing left? */
109         if (!*s) return(NULL);
110
111         do {
112                 ictok++;
113                 while(*s && (!strchr_m(sep,*s))) s++;
114                 while(*s && strchr_m(sep,*s)) *s++=0;
115         } while(*s);
116         
117         *ctok=ictok;
118         s=last_ptr;
119         
120         if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL;
121         
122         while(ictok--) {    
123                 *iret++=s;
124                 while(*s++);
125                 while(!*s) s++;
126         }
127
128         return ret;
129 }
130
131 /*******************************************************************
132   case insensitive string compararison
133 ********************************************************************/
134 int StrCaseCmp(const char *s, const char *t)
135 {
136         pstring buf1, buf2;
137         unix_strlower(s, strlen(s)+1, buf1, sizeof(buf1));
138         unix_strlower(t, strlen(t)+1, buf2, sizeof(buf2));
139         return strcmp(buf1,buf2);
140 }
141
142 /*******************************************************************
143   case insensitive string compararison, length limited
144 ********************************************************************/
145 int StrnCaseCmp(const char *s, const char *t, size_t n)
146 {
147    pstring buf1, buf2;
148    unix_strlower(s, strlen(s)+1, buf1, sizeof(buf1));
149    unix_strlower(t, strlen(t)+1, buf2, sizeof(buf2));
150    return strncmp(buf1,buf2,n);
151 }
152
153 /*******************************************************************
154   compare 2 strings 
155 ********************************************************************/
156 BOOL strequal(const char *s1, const char *s2)
157 {
158         if (s1 == s2) return(True);
159         if (!s1 || !s2) return(False);
160   
161         return(StrCaseCmp(s1,s2)==0);
162 }
163
164 /*******************************************************************
165   compare 2 strings up to and including the nth char.
166   ******************************************************************/
167 BOOL strnequal(const char *s1,const char *s2,size_t n)
168 {
169   if (s1 == s2) return(True);
170   if (!s1 || !s2 || !n) return(False);
171   
172   return(StrnCaseCmp(s1,s2,n)==0);
173 }
174
175 /*******************************************************************
176   compare 2 strings (case sensitive)
177 ********************************************************************/
178 BOOL strcsequal(const char *s1,const char *s2)
179 {
180   if (s1 == s2) return(True);
181   if (!s1 || !s2) return(False);
182   
183   return(strcmp(s1,s2)==0);
184 }
185
186 /***************************************************************************
187 Do a case-insensitive, whitespace-ignoring string compare.
188 ***************************************************************************/
189 int strwicmp(char *psz1, char *psz2)
190 {
191         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
192         /* appropriate value. */
193         if (psz1 == psz2)
194                 return (0);
195         else if (psz1 == NULL)
196                 return (-1);
197         else if (psz2 == NULL)
198                 return (1);
199
200         /* sync the strings on first non-whitespace */
201         while (1)
202         {
203                 while (isspace(*psz1))
204                         psz1++;
205                 while (isspace(*psz2))
206                         psz2++;
207                 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
208                     || *psz2 == '\0')
209                         break;
210                 psz1++;
211                 psz2++;
212         }
213         return (*psz1 - *psz2);
214 }
215
216
217 /*******************************************************************
218   convert a string to "normal" form
219 ********************************************************************/
220 void strnorm(char *s)
221 {
222   extern int case_default;
223   if (case_default == CASE_UPPER)
224     strupper(s);
225   else
226     strlower(s);
227 }
228
229 /*******************************************************************
230 check if a string is in "normal" case
231 ********************************************************************/
232 BOOL strisnormal(char *s)
233 {
234         extern int case_default;
235         if (case_default == CASE_UPPER)
236                 return(!strhaslower(s));
237         
238         return(!strhasupper(s));
239 }
240
241
242 /****************************************************************************
243   string replace
244   NOTE: oldc and newc must be 7 bit characters
245 ****************************************************************************/
246 void string_replace(char *s,char oldc,char newc)
247 {
248         smb_ucs2_t *ptr;
249         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
250         for(ptr=tmpbuf;*ptr;ptr++) {
251                 if(*ptr==UCS2_CHAR(oldc)) *ptr = UCS2_CHAR(newc);
252         }
253         pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
254 }
255
256
257 /*******************************************************************
258 skip past some strings in a buffer
259 ********************************************************************/
260 char *skip_string(char *buf,size_t n)
261 {
262         while (n--)
263                 buf += strlen(buf) + 1;
264         return(buf);
265 }
266
267 /*******************************************************************
268  Count the number of characters in a string. Normally this will
269  be the same as the number of bytes in a string for single byte strings,
270  but will be different for multibyte.
271 ********************************************************************/
272 size_t str_charnum(const char *s)
273 {
274         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
275         return strlen_w(tmpbuf);
276 }
277
278 /*******************************************************************
279 trim the specified elements off the front and back of a string
280 ********************************************************************/
281
282 BOOL trim_string(char *s,const char *front,const char *back)
283 {
284         BOOL ret = False;
285         size_t front_len;
286         size_t back_len;
287         size_t len;
288
289         /* Ignore null or empty strings. */
290         if (!s || (s[0] == '\0'))
291                 return False;
292
293         front_len       = front? strlen(front) : 0;
294         back_len        = back? strlen(back) : 0;
295
296         len = strlen(s);
297
298         if (front_len) {
299                 while (len && strncmp(s, front, front_len)==0) {
300                         memcpy(s, s+front_len, (len-front_len)+1);
301                         len -= front_len;
302                         ret=True;
303                 }
304         }
305         
306         if (back_len) {
307                 while (strncmp(s+len-back_len,back,back_len)==0) {
308                         s[len-back_len]='\0';
309                         len -= back_len;
310                         ret=True;
311                 }
312         }
313         return ret;
314 }
315
316
317 /****************************************************************************
318 does a string have any uppercase chars in it?
319 ****************************************************************************/
320 BOOL strhasupper(const char *s)
321 {
322         smb_ucs2_t *ptr;
323         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
324         for(ptr=tmpbuf;*ptr;ptr++)
325                 if(isupper_w(*ptr)) return True;
326         return(False);
327 }
328
329 /****************************************************************************
330 does a string have any lowercase chars in it?
331 ****************************************************************************/
332 BOOL strhaslower(const char *s)
333 {
334         smb_ucs2_t *ptr;
335         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
336         for(ptr=tmpbuf;*ptr;ptr++)
337                 if(islower_w(*ptr)) return True;
338         return(False);
339 }
340
341 /****************************************************************************
342 find the number of 'c' chars in a string
343 ****************************************************************************/
344 size_t count_chars(const char *s,char c)
345 {
346         smb_ucs2_t *ptr;
347         int count;
348         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
349         for(count=0,ptr=tmpbuf;*ptr;ptr++) if(*ptr==UCS2_CHAR(c)) count++;
350         return(count);
351 }
352
353 /*******************************************************************
354 Return True if a string consists only of one particular character.
355 ********************************************************************/
356
357 BOOL str_is_all(const char *s,char c)
358 {
359         smb_ucs2_t *ptr;
360
361         if(s == NULL) return False;
362         if(!*s) return False;
363   
364         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
365         for(ptr=tmpbuf;*ptr;ptr++) if(*ptr!=UCS2_CHAR(c)) return False;
366
367         return True;
368 }
369
370 /*******************************************************************
371 safe string copy into a known length string. maxlength does not
372 include the terminating zero.
373 ********************************************************************/
374
375 char *safe_strcpy(char *dest,const char *src, size_t maxlength)
376 {
377         size_t len;
378
379         if (!dest) {
380                 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
381                 return NULL;
382         }
383
384         if (!src) {
385                 *dest = 0;
386                 return dest;
387         }  
388
389         len = strlen(src);
390
391         if (len > maxlength) {
392                 DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
393                          (int)(len-maxlength), src));
394                 len = maxlength;
395         }
396       
397         memmove(dest, src, len);
398         dest[len] = 0;
399         return dest;
400 }  
401
402 /*******************************************************************
403 safe string cat into a string. maxlength does not
404 include the terminating zero.
405 ********************************************************************/
406
407 char *safe_strcat(char *dest, const char *src, size_t maxlength)
408 {
409         size_t src_len, dest_len;
410
411         if (!dest) {
412                 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
413                 return NULL;
414         }
415
416         if (!src) {
417                 return dest;
418         }  
419         
420         src_len = strlen(src);
421         dest_len = strlen(dest);
422         
423         if (src_len + dest_len > maxlength) {
424                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
425                          (int)(src_len + dest_len - maxlength), src));
426                 src_len = maxlength - dest_len;
427         }
428         
429         memcpy(&dest[dest_len], src, src_len);
430         dest[dest_len + src_len] = 0;
431         return dest;
432 }
433
434 /*******************************************************************
435  Paranoid strcpy into a buffer of given length (includes terminating
436  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
437  and replaces with '_'. Deliberately does *NOT* check for multibyte
438  characters. Don't change it !
439 ********************************************************************/
440
441 char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
442 {
443         size_t len, i;
444
445         if (!dest) {
446                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
447                 return NULL;
448         }
449
450         if (!src) {
451                 *dest = 0;
452                 return dest;
453         }  
454
455         len = strlen(src);
456         if (len >= maxlength)
457                 len = maxlength - 1;
458
459         if (!other_safe_chars)
460                 other_safe_chars = "";
461
462         for(i = 0; i < len; i++) {
463                 int val = (src[i] & 0xff);
464                 if(isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
465                         dest[i] = src[i];
466                 else
467                         dest[i] = '_';
468         }
469
470         dest[i] = '\0';
471
472         return dest;
473 }
474
475 /****************************************************************************
476  Like strncpy but always null terminates. Make sure there is room!
477  The variable n should always be one less than the available size.
478 ****************************************************************************/
479
480 char *StrnCpy(char *dest,const char *src,size_t n)
481 {
482         char *d = dest;
483         if (!dest) return(NULL);
484         if (!src) {
485                 *dest = 0;
486                 return(dest);
487         }
488         while (n-- && (*d++ = *src++)) ;
489         *d = 0;
490         return(dest);
491 }
492
493 /****************************************************************************
494 like strncpy but copies up to the character marker.  always null terminates.
495 returns a pointer to the character marker in the source string (src).
496 ****************************************************************************/
497 char *strncpyn(char *dest, const char *src,size_t n, char c)
498 {
499         char *p;
500         size_t str_len;
501
502         p = strchr_m(src, c);
503         if (p == NULL)
504         {
505                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
506                 return NULL;
507         }
508
509         str_len = PTR_DIFF(p, src);
510         strncpy(dest, src, MIN(n, str_len));
511         dest[str_len] = '\0';
512
513         return p;
514 }
515
516
517 /*************************************************************
518  Routine to get hex characters and turn them into a 16 byte array.
519  the array can be variable length, and any non-hex-numeric
520  characters are skipped.  "0xnn" or "0Xnn" is specially catered
521  for.
522
523  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
524
525 **************************************************************/
526 size_t strhex_to_str(char *p, size_t len, const char *strhex)
527 {
528         size_t i;
529         size_t num_chars = 0;
530         unsigned char   lonybble, hinybble;
531         char           *hexchars = "0123456789ABCDEF";
532         char           *p1 = NULL, *p2 = NULL;
533
534         for (i = 0; i < len && strhex[i] != 0; i++)
535         {
536                 if (strnequal(hexchars, "0x", 2))
537                 {
538                         i++; /* skip two chars */
539                         continue;
540                 }
541
542                 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
543                 {
544                         break;
545                 }
546
547                 i++; /* next hex digit */
548
549                 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
550                 {
551                         break;
552                 }
553
554                 /* get the two nybbles */
555                 hinybble = PTR_DIFF(p1, hexchars);
556                 lonybble = PTR_DIFF(p2, hexchars);
557
558                 p[num_chars] = (hinybble << 4) | lonybble;
559                 num_chars++;
560
561                 p1 = NULL;
562                 p2 = NULL;
563         }
564         return num_chars;
565 }
566
567 /****************************************************************************
568 check if a string is part of a list
569 ****************************************************************************/
570 BOOL in_list(char *s,char *list,BOOL casesensitive)
571 {
572   pstring tok;
573   char *p=list;
574
575   if (!list) return(False);
576
577   while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
578     if (casesensitive) {
579       if (strcmp(tok,s) == 0)
580         return(True);
581     } else {
582       if (StrCaseCmp(tok,s) == 0)
583         return(True);
584     }
585   }
586   return(False);
587 }
588
589 /* this is used to prevent lots of mallocs of size 1 */
590 static char *null_string = NULL;
591
592 /****************************************************************************
593 set a string value, allocing the space for the string
594 ****************************************************************************/
595 static BOOL string_init(char **dest,const char *src)
596 {
597   size_t l;
598   if (!src)     
599     src = "";
600
601   l = strlen(src);
602
603   if (l == 0)
604     {
605       if (!null_string) {
606         if((null_string = (char *)malloc(1)) == NULL) {
607           DEBUG(0,("string_init: malloc fail for null_string.\n"));
608           return False;
609         }
610         *null_string = 0;
611       }
612       *dest = null_string;
613     }
614   else
615     {
616       (*dest) = (char *)malloc(l+1);
617       if ((*dest) == NULL) {
618               DEBUG(0,("Out of memory in string_init\n"));
619               return False;
620       }
621
622       pstrcpy(*dest,src);
623     }
624   return(True);
625 }
626
627 /****************************************************************************
628 free a string value
629 ****************************************************************************/
630 void string_free(char **s)
631 {
632   if (!s || !(*s)) return;
633   if (*s == null_string)
634     *s = NULL;
635   SAFE_FREE(*s);
636 }
637
638 /****************************************************************************
639 set a string value, allocing the space for the string, and deallocating any 
640 existing space
641 ****************************************************************************/
642 BOOL string_set(char **dest,const char *src)
643 {
644   string_free(dest);
645
646   return(string_init(dest,src));
647 }
648
649
650 /****************************************************************************
651 substitute a string for a pattern in another string. Make sure there is 
652 enough room!
653
654 This routine looks for pattern in s and replaces it with 
655 insert. It may do multiple replacements.
656
657 any of " ; ' $ or ` in the insert string are replaced with _
658 if len==0 then no length check is performed
659 ****************************************************************************/
660 void string_sub(char *s,const char *pattern,const char *insert, size_t len)
661 {
662         char *p;
663         ssize_t ls,lp,li, i;
664
665         if (!insert || !pattern || !s) return;
666
667         ls = (ssize_t)strlen(s);
668         lp = (ssize_t)strlen(pattern);
669         li = (ssize_t)strlen(insert);
670
671         if (!*pattern) return;
672         
673         while (lp <= ls && (p = strstr(s,pattern))) {
674                 if (len && (ls + (li-lp) >= len)) {
675                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
676                                  (int)(ls + (li-lp) - len),
677                                  pattern, (int)len));
678                         break;
679                 }
680                 if (li != lp) {
681                         memmove(p+li,p+lp,strlen(p+lp)+1);
682                 }
683                 for (i=0;i<li;i++) {
684                         switch (insert[i]) {
685                         case '`':
686                         case '"':
687                         case '\'':
688                         case ';':
689                         case '$':
690                         case '%':
691                         case '\r':
692                         case '\n':
693                                 p[i] = '_';
694                                 break;
695                         default:
696                                 p[i] = insert[i];
697                         }
698                 }
699                 s = p + li;
700                 ls += (li-lp);
701         }
702 }
703
704 void fstring_sub(char *s,const char *pattern,const char *insert)
705 {
706         string_sub(s, pattern, insert, sizeof(fstring));
707 }
708
709 void pstring_sub(char *s,const char *pattern,const char *insert)
710 {
711         string_sub(s, pattern, insert, sizeof(pstring));
712 }
713
714 /****************************************************************************
715 similar to string_sub() but allows for any character to be substituted. 
716 Use with caution!
717 if len==0 then no length check is performed
718 ****************************************************************************/
719 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
720 {
721         char *p;
722         ssize_t ls,lp,li;
723
724         if (!insert || !pattern || !s) return;
725
726         ls = (ssize_t)strlen(s);
727         lp = (ssize_t)strlen(pattern);
728         li = (ssize_t)strlen(insert);
729
730         if (!*pattern) return;
731         
732         while (lp <= ls && (p = strstr(s,pattern))) {
733                 if (len && (ls + (li-lp) >= len)) {
734                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
735                                  (int)(ls + (li-lp) - len),
736                                  pattern, (int)len));
737                         break;
738                 }
739                 if (li != lp) {
740                         memmove(p+li,p+lp,strlen(p+lp)+1);
741                 }
742                 memcpy(p, insert, li);
743                 s = p + li;
744                 ls += (li-lp);
745         }
746 }
747
748 /****************************************************************************
749  splits out the front and back at a separator.
750 ****************************************************************************/
751 void split_at_last_component(char *path, char *front, char sep, char *back)
752 {
753         char *p = strrchr_m(path, sep);
754
755         if (p != NULL)
756         {
757                 *p = 0;
758         }
759         if (front != NULL)
760         {
761                 pstrcpy(front, path);
762         }
763         if (p != NULL)
764         {
765                 if (back != NULL)
766                 {
767                         pstrcpy(back, p+1);
768                 }
769                 *p = '\\';
770         }
771         else
772         {
773                 if (back != NULL)
774                 {
775                         back[0] = 0;
776                 }
777         }
778 }
779
780
781 /****************************************************************************
782 write an octal as a string
783 ****************************************************************************/
784 char *octal_string(int i)
785 {
786         static char ret[64];
787         if (i == -1) {
788                 return "-1";
789         }
790         slprintf(ret, sizeof(ret)-1, "0%o", i);
791         return ret;
792 }
793
794
795 /****************************************************************************
796 truncate a string at a specified length
797 ****************************************************************************/
798 char *string_truncate(char *s, int length)
799 {
800         if (s && strlen(s) > length) {
801                 s[length] = 0;
802         }
803         return s;
804 }
805
806
807 /****************************************************************************
808 strchr and strrchr_m are very hard to do on general multi-byte strings. 
809 we convert via ucs2 for now
810 ****************************************************************************/
811 char *strchr_m(const char *s, char c)
812 {
813         wpstring ws;
814         pstring s2;
815         smb_ucs2_t *p;
816
817         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
818         p = strchr_wa(ws, c);
819         if (!p) return NULL;
820         *p = 0;
821         pull_ucs2_pstring(s2, ws);
822         return (char *)(s+strlen(s2));
823 }
824
825 char *strrchr_m(const char *s, char c)
826 {
827         wpstring ws;
828         pstring s2;
829         smb_ucs2_t *p;
830
831         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
832         p = strrchr_wa(ws, c);
833         if (!p) return NULL;
834         *p = 0;
835         pull_ucs2_pstring(s2, ws);
836         return (char *)(s+strlen(s2));
837 }
838
839 /*******************************************************************
840   convert a string to lower case
841 ********************************************************************/
842 void strlower_m(char *s)
843 {
844         /* I assume that lowercased string takes the same number of bytes
845          * as source string even in UTF-8 encoding. (VIV) */
846         unix_strlower(s,strlen(s)+1,s,strlen(s)+1);     
847 }
848
849 /*******************************************************************
850   convert a string to upper case
851 ********************************************************************/
852 void strupper_m(char *s)
853 {
854         /* I assume that lowercased string takes the same number of bytes
855          * as source string even in multibyte encoding. (VIV) */
856         unix_strupper(s,strlen(s)+1,s,strlen(s)+1);     
857 }
858