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