2 Unix SMB/Netbios implementation.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern int DEBUGLEVEL
;
26 static char *last_ptr
=NULL
;
28 void set_first_token(char *ptr
)
33 /****************************************************************************
34 Get the next token from a string, return False if none found
35 handles double-quotes.
36 Based on a routine by GJC@VILLAGE.COM.
37 Extensively modified by Andrew.Tridgell@anu.edu.au
38 ****************************************************************************/
39 BOOL
next_token(char **ptr
,char *buff
,char *sep
, size_t bufsize
)
45 if (!ptr
) ptr
= &last_ptr
;
46 if (!ptr
) return(False
);
50 /* default to simple separators */
51 if (!sep
) sep
= " \t\n\r";
53 /* find the first non sep char */
54 while(*s
&& strchr(sep
,*s
)) s
++;
57 if (! *s
) return(False
);
59 /* copy over the token */
60 for (quoted
= False
; len
< bufsize
&& *s
&& (quoted
|| !strchr(sep
,*s
)); s
++)
70 *ptr
= (*s
) ? s
+1 : s
;
77 /****************************************************************************
78 Convert list of tokens to array; dependent on above routine.
79 Uses last_ptr from above - bit of a hack.
80 ****************************************************************************/
81 char **toktocliplist(int *ctok
, char *sep
)
87 if (!sep
) sep
= " \t\n\r";
89 while(*s
&& strchr(sep
,*s
)) s
++;
92 if (!*s
) return(NULL
);
96 while(*s
&& (!strchr(sep
,*s
))) s
++;
97 while(*s
&& strchr(sep
,*s
)) *s
++=0;
103 if (!(ret
=iret
=malloc(ictok
*sizeof(char *)))) return NULL
;
115 /*******************************************************************
116 case insensitive string compararison
117 ********************************************************************/
118 int StrCaseCmp(const char *s
, const char *t
)
120 /* compare until we run out of string, either t or s, or find a difference */
121 /* We *must* use toupper rather than tolower here due to the
122 asynchronous upper to lower mapping.
124 #if !defined(KANJI_WIN95_COMPATIBILITY)
126 * For completeness we should put in equivalent code for code pages
127 * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
128 * doubt anyone wants Samba to behave differently from Win95 and WinNT
129 * here. They both treat full width ascii characters as case senstive
130 * filenames (ie. they don't do the work we do here).
134 if(lp_client_code_page() == KANJI_CODEPAGE
)
136 /* Win95 treats full width ascii characters as case sensitive. */
141 return toupper (*s
) - toupper (*t
);
142 else if (is_sj_alph (*s
) && is_sj_alph (*t
))
144 diff
= sj_toupper2 (*(s
+1)) - sj_toupper2 (*(t
+1));
150 else if (is_shift_jis (*s
) && is_shift_jis (*t
))
152 diff
= ((int) (unsigned char) *s
) - ((int) (unsigned char) *t
);
155 diff
= ((int) (unsigned char) *(s
+1)) - ((int) (unsigned char) *(t
+1));
161 else if (is_shift_jis (*s
))
163 else if (is_shift_jis (*t
))
167 diff
= toupper (*s
) - toupper (*t
);
176 #endif /* KANJI_WIN95_COMPATIBILITY */
178 while (*s
&& *t
&& toupper(*s
) == toupper(*t
))
184 return(toupper(*s
) - toupper(*t
));
188 /*******************************************************************
189 case insensitive string compararison, length limited
190 ********************************************************************/
191 int StrnCaseCmp(const char *s
, const char *t
, size_t n
)
193 /* compare until we run out of string, either t or s, or chars */
194 /* We *must* use toupper rather than tolower here due to the
195 asynchronous upper to lower mapping.
197 #if !defined(KANJI_WIN95_COMPATIBILITY)
199 * For completeness we should put in equivalent code for code pages
200 * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
201 * doubt anyone wants Samba to behave differently from Win95 and WinNT
202 * here. They both treat full width ascii characters as case senstive
203 * filenames (ie. they don't do the work we do here).
207 if(lp_client_code_page() == KANJI_CODEPAGE
)
209 /* Win95 treats full width ascii characters as case sensitive. */
214 return toupper (*s
) - toupper (*t
);
215 else if (is_sj_alph (*s
) && is_sj_alph (*t
))
217 diff
= sj_toupper2 (*(s
+1)) - sj_toupper2 (*(t
+1));
224 else if (is_shift_jis (*s
) && is_shift_jis (*t
))
226 diff
= ((int) (unsigned char) *s
) - ((int) (unsigned char) *t
);
229 diff
= ((int) (unsigned char) *(s
+1)) - ((int) (unsigned char) *(t
+1));
236 else if (is_shift_jis (*s
))
238 else if (is_shift_jis (*t
))
242 diff
= toupper (*s
) - toupper (*t
);
253 #endif /* KANJI_WIN95_COMPATIBILITY */
255 while (n
&& *s
&& *t
&& toupper(*s
) == toupper(*t
))
262 /* not run out of chars - strings are different lengths */
264 return(toupper(*s
) - toupper(*t
));
266 /* identical up to where we run out of chars,
267 and strings are same length */
272 /*******************************************************************
274 ********************************************************************/
275 BOOL
strequal(const char *s1
, const char *s2
)
277 if (s1
== s2
) return(True
);
278 if (!s1
|| !s2
) return(False
);
280 return(StrCaseCmp(s1
,s2
)==0);
283 /*******************************************************************
284 compare 2 strings up to and including the nth char.
285 ******************************************************************/
286 BOOL
strnequal(const char *s1
,const char *s2
,size_t n
)
288 if (s1
== s2
) return(True
);
289 if (!s1
|| !s2
|| !n
) return(False
);
291 return(StrnCaseCmp(s1
,s2
,n
)==0);
294 /*******************************************************************
295 compare 2 strings (case sensitive)
296 ********************************************************************/
297 BOOL
strcsequal(const char *s1
,const char *s2
)
299 if (s1
== s2
) return(True
);
300 if (!s1
|| !s2
) return(False
);
302 return(strcmp(s1
,s2
)==0);
306 /*******************************************************************
307 convert a string to lower case
308 ********************************************************************/
309 void strlower(char *s
)
313 #if !defined(KANJI_WIN95_COMPATIBILITY)
315 * For completeness we should put in equivalent code for code pages
316 * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
317 * doubt anyone wants Samba to behave differently from Win95 and WinNT
318 * here. They both treat full width ascii characters as case senstive
319 * filenames (ie. they don't do the work we do here).
323 if(lp_client_code_page() == KANJI_CODEPAGE
)
325 /* Win95 treats full width ascii characters as case sensitive. */
326 if (is_shift_jis (*s
))
328 if (is_sj_upper (s
[0], s
[1]))
329 s
[1] = sj_tolower2 (s
[1]);
332 else if (is_kana (*s
))
344 #endif /* KANJI_WIN95_COMPATIBILITY */
346 size_t skip
= get_character_len( *s
);
359 /*******************************************************************
360 convert a string to upper case
361 ********************************************************************/
362 void strupper(char *s
)
366 #if !defined(KANJI_WIN95_COMPATIBILITY)
368 * For completeness we should put in equivalent code for code pages
369 * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
370 * doubt anyone wants Samba to behave differently from Win95 and WinNT
371 * here. They both treat full width ascii characters as case senstive
372 * filenames (ie. they don't do the work we do here).
376 if(lp_client_code_page() == KANJI_CODEPAGE
)
378 /* Win95 treats full width ascii characters as case sensitive. */
379 if (is_shift_jis (*s
))
381 if (is_sj_lower (s
[0], s
[1]))
382 s
[1] = sj_toupper2 (s
[1]);
385 else if (is_kana (*s
))
397 #endif /* KANJI_WIN95_COMPATIBILITY */
399 size_t skip
= get_character_len( *s
);
412 /*******************************************************************
413 convert a string to "normal" form
414 ********************************************************************/
415 void strnorm(char *s
)
417 extern int case_default
;
418 if (case_default
== CASE_UPPER
)
424 /*******************************************************************
425 check if a string is in "normal" case
426 ********************************************************************/
427 BOOL
strisnormal(char *s
)
429 extern int case_default
;
430 if (case_default
== CASE_UPPER
)
431 return(!strhaslower(s
));
433 return(!strhasupper(s
));
437 /****************************************************************************
439 ****************************************************************************/
440 void string_replace(char *s
,char oldc
,char newc
)
447 if(!global_is_multibyte_codepage
) {
456 skip
= get_character_len( *s
);
470 /*******************************************************************
471 skip past some strings in a buffer
472 ********************************************************************/
473 char *skip_string(char *buf
,size_t n
)
476 buf
+= strlen(buf
) + 1;
480 /*******************************************************************
481 Count the number of characters in a string. Normally this will
482 be the same as the number of bytes in a string for single byte strings,
483 but will be different for multibyte.
484 16.oct.98, jdblair@cobaltnet.com.
485 ********************************************************************/
487 size_t str_charnum(const char *s
)
494 if(!global_is_multibyte_codepage
) {
498 int skip
= get_character_len(*s
);
499 s
+= (skip
? skip
: 1);
506 /*******************************************************************
507 trim the specified elements off the front and back of a string
508 ********************************************************************/
510 BOOL
trim_string(char *s
,const char *front
,const char *back
)
513 size_t front_len
= (front
&& *front
) ? strlen(front
) : 0;
514 size_t back_len
= (back
&& *back
) ? strlen(back
) : 0;
517 while (front_len
&& strncmp(s
, front
, front_len
) == 0)
523 if (!(*p
= p
[front_len
]))
530 * We split out the multibyte code page
531 * case here for speed purposes. Under a
532 * multibyte code page we need to walk the
533 * string forwards only and multiple times.
534 * Thanks to John Blair for finding this
540 if(!global_is_multibyte_codepage
)
543 while ((s_len
>= back_len
) &&
544 (strncmp(s
+ s_len
- back_len
, back
, back_len
)==0))
547 s
[s_len
- back_len
] = '\0';
555 * Multibyte code page case.
556 * Keep going through the string, trying
557 * to match the 'back' string with the end
558 * of the string. If we get a match, truncate
559 * 'back' off the end of the string and
560 * go through the string again from the
561 * start. Keep doing this until we have
562 * gone through the string with no match
566 size_t mb_back_len
= str_charnum(back
);
567 size_t mb_s_len
= str_charnum(s
);
569 while(mb_s_len
>= mb_back_len
)
571 size_t charcount
= 0;
577 if(!global_is_multibyte_codepage
) {
578 while(charcount
< (mb_s_len
- mb_back_len
)) {
583 while(charcount
< (mb_s_len
- mb_back_len
)) {
584 size_t skip
= skip_multibyte_char(*mbp
);
585 mbp
+= (skip
? skip
: 1);
591 * mbp now points at mb_back_len multibyte
592 * characters from the end of s.
595 if(strcmp(mbp
, back
) == 0)
599 mb_s_len
= str_charnum(s
);
604 } /* end while mb_s_len... */
606 } /* end if back_len .. */
612 /****************************************************************************
613 does a string have any uppercase chars in it?
614 ****************************************************************************/
615 BOOL
strhasupper(const char *s
)
619 #if !defined(KANJI_WIN95_COMPATIBILITY)
621 * For completeness we should put in equivalent code for code pages
622 * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
623 * doubt anyone wants Samba to behave differently from Win95 and WinNT
624 * here. They both treat full width ascii characters as case senstive
625 * filenames (ie. they don't do the work we do here).
629 if(lp_client_code_page() == KANJI_CODEPAGE
)
631 /* Win95 treats full width ascii characters as case sensitive. */
632 if (is_shift_jis (*s
))
634 else if (is_kana (*s
))
644 #endif /* KANJI_WIN95_COMPATIBILITY */
646 size_t skip
= get_character_len( *s
);
659 /****************************************************************************
660 does a string have any lowercase chars in it?
661 ****************************************************************************/
662 BOOL
strhaslower(const char *s
)
666 #if !defined(KANJI_WIN95_COMPATIBILITY)
668 * For completeness we should put in equivalent code for code pages
669 * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
670 * doubt anyone wants Samba to behave differently from Win95 and WinNT
671 * here. They both treat full width ascii characters as case senstive
672 * filenames (ie. they don't do the work we do here).
676 if(lp_client_code_page() == KANJI_CODEPAGE
)
678 /* Win95 treats full width ascii characters as case sensitive. */
679 if (is_shift_jis (*s
))
681 if (is_sj_upper (s
[0], s
[1]))
683 if (is_sj_lower (s
[0], s
[1]))
687 else if (is_kana (*s
))
699 #endif /* KANJI_WIN95_COMPATIBILITY */
701 size_t skip
= get_character_len( *s
);
714 /****************************************************************************
715 find the number of chars in a string
716 ****************************************************************************/
717 size_t count_chars(const char *s
,char c
)
721 #if !defined(KANJI_WIN95_COMPATIBILITY)
723 * For completeness we should put in equivalent code for code pages
724 * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
725 * doubt anyone wants Samba to behave differently from Win95 and WinNT
726 * here. They both treat full width ascii characters as case senstive
727 * filenames (ie. they don't do the work we do here).
731 if(lp_client_code_page() == KANJI_CODEPAGE
)
733 /* Win95 treats full width ascii characters as case sensitive. */
736 if (is_shift_jis (*s
))
747 #endif /* KANJI_WIN95_COMPATIBILITY */
751 size_t skip
= get_character_len( *s
);
764 /*******************************************************************
765 Return True if a string consists only of one particular character.
766 ********************************************************************/
768 BOOL
str_is_all(const char *s
,char c
)
775 #if !defined(KANJI_WIN95_COMPATIBILITY)
777 * For completeness we should put in equivalent code for code pages
778 * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
779 * doubt anyone wants Samba to behave differently from Win95 and WinNT
780 * here. They both treat full width ascii characters as case senstive
781 * filenames (ie. they don't do the work we do here).
785 if(lp_client_code_page() == KANJI_CODEPAGE
)
787 /* Win95 treats full width ascii characters as case sensitive. */
790 if (is_shift_jis (*s
))
801 #endif /* KANJI_WIN95_COMPATIBILITY */
805 size_t skip
= get_character_len( *s
);
818 /*******************************************************************
819 safe string copy into a known length string. maxlength does not
820 include the terminating zero.
821 ********************************************************************/
822 char *safe_strcpy(char *dest
,const char *src
, size_t maxlength
)
827 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
838 if (len
> maxlength
) {
839 DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
840 (int)(len
-maxlength
), src
));
841 SMB_ASSERT(len
<= maxlength
);
845 memcpy(dest
, src
, len
);
850 /*******************************************************************
851 safe string cat into a string. maxlength does not
852 include the terminating zero.
853 ********************************************************************/
854 char *safe_strcat(char *dest
, const char *src
, size_t maxlength
)
856 size_t src_len
, dest_len
;
859 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
867 src_len
= strlen(src
);
868 dest_len
= strlen(dest
);
870 if (src_len
+ dest_len
> maxlength
) {
871 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
872 (int)(src_len
+ dest_len
- maxlength
), src
));
874 src_len
= maxlength
- dest_len
;
877 memcpy(&dest
[dest_len
], src
, src_len
);
878 dest
[dest_len
+ src_len
] = 0;
882 /*******************************************************************
883 Paranoid strcpy into a buffer of given length (includes terminating
884 zero. Strips out all but 'a-Z0-9' and replaces with '_'. Deliberately
885 does *NOT* check for multibyte characters. Don't change it !
886 ********************************************************************/
888 char *alpha_strcpy(char *dest
, const char *src
, size_t maxlength
)
893 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
903 if (len
>= maxlength
)
906 for(i
= 0; i
< len
; i
++) {
907 int val
= (src
[i
] & 0xff);
908 if(isupper(val
) ||islower(val
) || isdigit(val
))
919 /****************************************************************************
920 Like strncpy but always null terminates. Make sure there is room!
921 The variable n should always be one less than the available size.
922 ****************************************************************************/
923 char *StrnCpy(char *dest
,const char *src
,size_t n
)
926 if (!dest
) return(NULL
);
931 while (n
-- && (*d
++ = *src
++)) ;
937 /****************************************************************************
938 like strncpy but copies up to the character marker. always null terminates.
939 returns a pointer to the character marker in the source string (src).
940 ****************************************************************************/
941 char *strncpyn(char *dest
, const char *src
,size_t n
, char c
)
949 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c
));
953 str_len
= PTR_DIFF(p
, src
);
954 strncpy(dest
, src
, MIN(n
, str_len
));
955 dest
[str_len
] = '\0';
961 /*************************************************************
962 Routine to get hex characters and turn them into a 16 byte array.
963 the array can be variable length, and any non-hex-numeric
964 characters are skipped. "0xnn" or "0Xnn" is specially catered
967 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
969 **************************************************************/
970 size_t strhex_to_str(char *p
, size_t len
, const char *strhex
)
973 size_t num_chars
= 0;
974 unsigned char lonybble
, hinybble
;
975 char *hexchars
= "0123456789ABCDEF";
976 char *p1
= NULL
, *p2
= NULL
;
978 for (i
= 0; i
< len
&& strhex
[i
] != 0; i
++)
980 if (strnequal(hexchars
, "0x", 2))
982 i
++; /* skip two chars */
986 if (!(p1
= strchr(hexchars
, toupper(strhex
[i
]))))
991 i
++; /* next hex digit */
993 if (!(p2
= strchr(hexchars
, toupper(strhex
[i
]))))
998 /* get the two nybbles */
999 hinybble
= PTR_DIFF(p1
, hexchars
);
1000 lonybble
= PTR_DIFF(p2
, hexchars
);
1002 p
[num_chars
] = (hinybble
<< 4) | lonybble
;
1011 /****************************************************************************
1012 check if a string is part of a list
1013 ****************************************************************************/
1014 BOOL
in_list(char *s
,char *list
,BOOL casesensitive
)
1019 if (!list
) return(False
);
1021 while (next_token(&p
,tok
,LIST_SEP
,sizeof(tok
))) {
1022 if (casesensitive
) {
1023 if (strcmp(tok
,s
) == 0)
1026 if (StrCaseCmp(tok
,s
) == 0)
1033 /* this is used to prevent lots of mallocs of size 1 */
1034 static char *null_string
= NULL
;
1036 /****************************************************************************
1037 set a string value, allocing the space for the string
1038 ****************************************************************************/
1039 static BOOL
string_init(char **dest
,const char *src
)
1050 if((null_string
= (char *)malloc(1)) == NULL
) {
1051 DEBUG(0,("string_init: malloc fail for null_string.\n"));
1056 *dest
= null_string
;
1060 (*dest
) = (char *)malloc(l
+1);
1061 if ((*dest
) == NULL
) {
1062 DEBUG(0,("Out of memory in string_init\n"));
1071 /****************************************************************************
1073 ****************************************************************************/
1074 void string_free(char **s
)
1076 if (!s
|| !(*s
)) return;
1077 if (*s
== null_string
)
1083 /****************************************************************************
1084 set a string value, allocing the space for the string, and deallocating any
1086 ****************************************************************************/
1087 BOOL
string_set(char **dest
,const char *src
)
1091 return(string_init(dest
,src
));
1095 /****************************************************************************
1096 substitute a string for a pattern in another string. Make sure there is
1099 This routine looks for pattern in s and replaces it with
1100 insert. It may do multiple replacements.
1102 any of " ; ' $ or ` in the insert string are replaced with _
1103 if len==0 then no length check is performed
1104 ****************************************************************************/
1105 void string_sub(char *s
,const char *pattern
,const char *insert
, size_t len
)
1108 ssize_t ls
,lp
,li
, i
;
1110 if (!insert
|| !pattern
|| !s
) return;
1112 ls
= (ssize_t
)strlen(s
);
1113 lp
= (ssize_t
)strlen(pattern
);
1114 li
= (ssize_t
)strlen(insert
);
1116 if (!*pattern
) return;
1118 while (lp
<= ls
&& (p
= strstr(s
,pattern
))) {
1119 if (len
&& (ls
+ (li
-lp
) >= len
)) {
1120 DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n",
1121 (int)(ls
+ (li
-lp
) - len
),
1122 pattern
, (int)len
));
1127 memmove(p
+li
,p
+lp
,strlen(p
+lp
)+1);
1129 for (i
=0;i
<li
;i
++) {
1130 switch (insert
[i
]) {
1150 void fstring_sub(char *s
,const char *pattern
,const char *insert
)
1152 string_sub(s
, pattern
, insert
, sizeof(fstring
));
1155 void pstring_sub(char *s
,const char *pattern
,const char *insert
)
1157 string_sub(s
, pattern
, insert
, sizeof(pstring
));
1160 /****************************************************************************
1161 similar to string_sub() but allows for any character to be substituted.
1163 if len==0 then no length check is performed
1164 ****************************************************************************/
1165 void all_string_sub(char *s
,const char *pattern
,const char *insert
, size_t len
)
1170 if (!insert
|| !pattern
|| !s
) return;
1172 ls
= (ssize_t
)strlen(s
);
1173 lp
= (ssize_t
)strlen(pattern
);
1174 li
= (ssize_t
)strlen(insert
);
1176 if (!*pattern
) return;
1178 while (lp
<= ls
&& (p
= strstr(s
,pattern
))) {
1179 if (len
&& (ls
+ (li
-lp
) >= len
)) {
1180 DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n",
1181 (int)(ls
+ (li
-lp
) - len
),
1182 pattern
, (int)len
));
1186 memmove(p
+li
,p
+lp
,strlen(p
+lp
)+1);
1188 memcpy(p
, insert
, li
);
1194 /****************************************************************************
1195 splits out the front and back at a separator.
1196 ****************************************************************************/
1197 void split_at_first_component(char *path
, char *front
, char sep
, char *back
)
1199 char *p
= strchr(path
, sep
);
1207 pstrcpy(front
, path
);
1226 /****************************************************************************
1227 splits out the front and back at a separator.
1228 ****************************************************************************/
1229 void split_at_last_component(char *path
, char *front
, char sep
, char *back
)
1231 char *p
= strrchr(path
, sep
);
1239 pstrcpy(front
, path
);
1241 else if (back
!= NULL
)
1243 pstrcpy(back
, path
);
1255 if (back
!= NULL
&& front
!= NULL
)
1262 /****************************************************************************
1263 convert a bit field to a string. if you want multiple bits to be detected
1264 set them first, e.g SV_TYPE_ALL to be "All" or "Full Control" for ACB_INFOs.
1266 strings are expected to contain their own separators, although the code
1267 below only assumes that separators are spaces.
1269 ****************************************************************************/
1270 char *bit_field_to_str(uint32 type
, struct field_info
*bs
)
1272 static fstring typestr
;
1277 if (type
== 0 || bs
== NULL
)
1282 while (bs
[i
].str
!= NULL
&& type
!= 0)
1284 if (IS_BITS_SET_ALL(bs
[i
].bits
, type
))
1286 fstrcat(typestr
, bs
[i
].str
);
1287 type
&= ~bs
[i
].bits
;
1292 i
= strlen(typestr
)-1;
1293 if (i
> 0 && typestr
[i
] == ' ')
1301 /****************************************************************************
1302 convert an enumeration to a string. first item is the default.
1303 ****************************************************************************/
1304 char *enum_field_to_str(uint32 type
, struct field_info
*bs
, BOOL first_default
)
1313 while (bs
[i
].str
!= NULL
&& type
!= 0)
1315 if (bs
[i
].bits
== type
)
1322 /* oops - none found */
1332 /****************************************************************************
1333 write an octal as a string
1334 ****************************************************************************/
1335 char *octal_string(int i
)
1337 static char ret
[64];
1341 slprintf(ret
, sizeof(ret
), "0%o", i
);
1346 /****************************************************************************
1347 truncate a string at a specified length
1348 ****************************************************************************/
1349 char *string_truncate(char *s
, int length
)
1351 if (s
&& strlen(s
) > length
) {