root/src/vfs/smbfs/helpers/lib/util_str.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. set_first_token
  2. next_token
  3. toktocliplist
  4. StrCaseCmp
  5. StrnCaseCmp
  6. strequal
  7. strnequal
  8. strcsequal
  9. strlower
  10. strupper
  11. strnorm
  12. strisnormal
  13. string_replace
  14. skip_string
  15. str_charnum
  16. trim_string
  17. strhasupper
  18. strhaslower
  19. count_chars
  20. safe_strcpy
  21. safe_strcat
  22. StrCpy
  23. StrnCpy
  24. strncpyn
  25. strhex_to_str
  26. in_list
  27. string_init
  28. string_free
  29. string_set
  30. string_sub
  31. all_string_sub
  32. split_at_last_component

   1 /*
   2    Unix SMB/Netbios implementation.
   3    Version 1.9.
   4    Samba utility functions
   5 
   6    Copyright (C) Andrew Tridgell 1992-1998
   7 
   8    Copyright (C) 2011-2019
   9    Free Software Foundation, Inc.
  10 
  11    This file is part of the Midnight Commander.
  12 
  13    The Midnight Commander is free software: you can redistribute it
  14    and/or modify it under the terms of the GNU General Public License as
  15    published by the Free Software Foundation, either version 3 of the License,
  16    or (at your option) any later version.
  17 
  18    The Midnight Commander is distributed in the hope that it will be useful,
  19    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21    GNU General Public License for more details.
  22 
  23    You should have received a copy of the GNU General Public License
  24    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25  */
  26 
  27 #include "includes.h"
  28 
  29 extern int DEBUGLEVEL;
  30 
  31 static char *last_ptr = NULL;
  32 
  33 void
  34 set_first_token (char *ptr)
     /* [previous][next][first][last][top][bottom][index][help]  */
  35 {
  36     last_ptr = ptr;
  37 }
  38 
  39 /****************************************************************************
  40   Get the next token from a string, return False if none found
  41   handles double-quotes. 
  42 Based on a routine by GJC@VILLAGE.COM. 
  43 Extensively modified by Andrew.Tridgell@anu.edu.au
  44 ****************************************************************************/
  45 BOOL
  46 next_token (char **ptr, char *buff, const char *sep, size_t bufsize)
     /* [previous][next][first][last][top][bottom][index][help]  */
  47 {
  48     char *s;
  49     BOOL quoted;
  50     size_t len = 1;
  51 
  52     if (!ptr)
  53         ptr = &last_ptr;
  54     if (!ptr)
  55         return (False);
  56 
  57     s = *ptr;
  58 
  59     /* default to simple separators */
  60     if (!sep)
  61         sep = " \t\n\r";
  62 
  63     /* find the first non sep char */
  64     while (*s && strchr (sep, *s))
  65         s++;
  66 
  67     /* nothing left? */
  68     if (!*s)
  69         return (False);
  70 
  71     /* copy over the token */
  72     for (quoted = False; len < bufsize && *s && (quoted || !strchr (sep, *s)); s++)
  73     {
  74         if (*s == '\"')
  75         {
  76             quoted = !quoted;
  77         }
  78         else
  79         {
  80             len++;
  81             *buff++ = *s;
  82         }
  83     }
  84 
  85     *ptr = (*s) ? s + 1 : s;
  86     *buff = 0;
  87     last_ptr = *ptr;
  88 
  89     return (True);
  90 }
  91 
  92 #if 0
  93 /****************************************************************************
  94 Convert list of tokens to array; dependent on above routine.
  95 Uses last_ptr from above - bit of a hack.
  96 ****************************************************************************/
  97 char **
  98 toktocliplist (int *ctok, char *sep)
     /* [previous][next][first][last][top][bottom][index][help]  */
  99 {
 100     char *s = last_ptr;
 101     int ictok = 0;
 102     char **ret, **iret;
 103 
 104     if (!sep)
 105         sep = " \t\n\r";
 106 
 107     while (*s && strchr (sep, *s))
 108         s++;
 109 
 110     /* nothing left? */
 111     if (!*s)
 112         return (NULL);
 113 
 114     do
 115     {
 116         ictok++;
 117         while (*s && (!strchr (sep, *s)))
 118             s++;
 119         while (*s && strchr (sep, *s))
 120             *s++ = 0;
 121     }
 122     while (*s);
 123 
 124     *ctok = ictok;
 125     s = last_ptr;
 126 
 127     if (!(ret = iret = malloc (ictok * sizeof (char *))))
 128         return NULL;
 129 
 130     while (ictok--)
 131     {
 132         *iret++ = s;
 133         while (*s++);
 134         while (!*s)
 135             s++;
 136     }
 137 
 138     return ret;
 139 }
 140 #endif /*0 */
 141 
 142 /*******************************************************************
 143   case insensitive string compararison
 144 ********************************************************************/
 145 int
 146 StrCaseCmp (const char *s, const char *t)
     /* [previous][next][first][last][top][bottom][index][help]  */
 147 {
 148     /* compare until we run out of string, either t or s, or find a difference */
 149     /* We *must* use toupper rather than tolower here due to the
 150        asynchronous upper to lower mapping.
 151      */
 152 #if !defined(KANJI_WIN95_COMPATIBILITY)
 153     /*
 154      * For completeness we should put in equivalent code for code pages
 155      * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
 156      * doubt anyone wants Samba to behave differently from Win95 and WinNT
 157      * here. They both treat full width ascii characters as case senstive
 158      * filenames (ie. they don't do the work we do here).
 159      * JRA.
 160      */
 161 
 162     if (lp_client_code_page () == KANJI_CODEPAGE)
 163     {
 164         /* Win95 treats full width ascii characters as case sensitive. */
 165         int diff;
 166         for (;;)
 167         {
 168             if (!*s || !*t)
 169                 return toupper (*s) - toupper (*t);
 170             else if (is_sj_alph (*s) && is_sj_alph (*t))
 171             {
 172                 diff = sj_toupper2 (*(s + 1)) - sj_toupper2 (*(t + 1));
 173                 if (diff)
 174                     return diff;
 175                 s += 2;
 176                 t += 2;
 177             }
 178             else if (is_shift_jis (*s) && is_shift_jis (*t))
 179             {
 180                 diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
 181                 if (diff)
 182                     return diff;
 183                 diff = ((int) (unsigned char) *(s + 1)) - ((int) (unsigned char) *(t + 1));
 184                 if (diff)
 185                     return diff;
 186                 s += 2;
 187                 t += 2;
 188             }
 189             else if (is_shift_jis (*s))
 190                 return 1;
 191             else if (is_shift_jis (*t))
 192                 return -1;
 193             else
 194             {
 195                 diff = toupper (*s) - toupper (*t);
 196                 if (diff)
 197                     return diff;
 198                 s++;
 199                 t++;
 200             }
 201         }
 202     }
 203     else
 204 #endif /* KANJI_WIN95_COMPATIBILITY */
 205     {
 206         while (*s && *t && toupper (*s) == toupper (*t))
 207         {
 208             s++;
 209             t++;
 210         }
 211 
 212         return (toupper (*s) - toupper (*t));
 213     }
 214 }
 215 
 216 /*******************************************************************
 217   case insensitive string compararison, length limited
 218 ********************************************************************/
 219 int
 220 StrnCaseCmp (const char *s, const char *t, size_t n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 221 {
 222     /* compare until we run out of string, either t or s, or chars */
 223     /* We *must* use toupper rather than tolower here due to the
 224        asynchronous upper to lower mapping.
 225      */
 226 #if !defined(KANJI_WIN95_COMPATIBILITY)
 227     /*
 228      * For completeness we should put in equivalent code for code pages
 229      * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
 230      * doubt anyone wants Samba to behave differently from Win95 and WinNT
 231      * here. They both treat full width ascii characters as case senstive
 232      * filenames (ie. they don't do the work we do here).
 233      * JRA. 
 234      */
 235 
 236     if (lp_client_code_page () == KANJI_CODEPAGE)
 237     {
 238         /* Win95 treats full width ascii characters as case sensitive. */
 239         int diff;
 240         for (; n > 0;)
 241         {
 242             if (!*s || !*t)
 243                 return toupper (*s) - toupper (*t);
 244             else if (is_sj_alph (*s) && is_sj_alph (*t))
 245             {
 246                 diff = sj_toupper2 (*(s + 1)) - sj_toupper2 (*(t + 1));
 247                 if (diff)
 248                     return diff;
 249                 s += 2;
 250                 t += 2;
 251                 n -= 2;
 252             }
 253             else if (is_shift_jis (*s) && is_shift_jis (*t))
 254             {
 255                 diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
 256                 if (diff)
 257                     return diff;
 258                 diff = ((int) (unsigned char) *(s + 1)) - ((int) (unsigned char) *(t + 1));
 259                 if (diff)
 260                     return diff;
 261                 s += 2;
 262                 t += 2;
 263                 n -= 2;
 264             }
 265             else if (is_shift_jis (*s))
 266                 return 1;
 267             else if (is_shift_jis (*t))
 268                 return -1;
 269             else
 270             {
 271                 diff = toupper (*s) - toupper (*t);
 272                 if (diff)
 273                     return diff;
 274                 s++;
 275                 t++;
 276                 n--;
 277             }
 278         }
 279         return 0;
 280     }
 281     else
 282 #endif /* KANJI_WIN95_COMPATIBILITY */
 283     {
 284         while (n && *s && *t && toupper (*s) == toupper (*t))
 285         {
 286             s++;
 287             t++;
 288             n--;
 289         }
 290 
 291         /* not run out of chars - strings are different lengths */
 292         if (n)
 293             return (toupper (*s) - toupper (*t));
 294 
 295         /* identical up to where we run out of chars, 
 296            and strings are same length */
 297         return (0);
 298     }
 299 }
 300 
 301 /*******************************************************************
 302   compare 2 strings 
 303 ********************************************************************/
 304 BOOL
 305 strequal (const char *s1, const char *s2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 306 {
 307     if (s1 == s2)
 308         return (True);
 309     if (!s1 || !s2)
 310         return (False);
 311 
 312     return (StrCaseCmp (s1, s2) == 0);
 313 }
 314 
 315 /*******************************************************************
 316   compare 2 strings up to and including the nth char.
 317   ******************************************************************/
 318 BOOL
 319 strnequal (const char *s1, const char *s2, size_t n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 320 {
 321     if (s1 == s2)
 322         return (True);
 323     if (!s1 || !s2 || !n)
 324         return (False);
 325 
 326     return (StrnCaseCmp (s1, s2, n) == 0);
 327 }
 328 
 329 /*******************************************************************
 330   compare 2 strings (case sensitive)
 331 ********************************************************************/
 332 BOOL
 333 strcsequal (const char *s1, const char *s2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 334 {
 335     if (s1 == s2)
 336         return (True);
 337     if (!s1 || !s2)
 338         return (False);
 339 
 340     return (strcmp (s1, s2) == 0);
 341 }
 342 
 343 
 344 /*******************************************************************
 345   convert a string to lower case
 346 ********************************************************************/
 347 void
 348 strlower (char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 349 {
 350     while (*s)
 351     {
 352 #if !defined(KANJI_WIN95_COMPATIBILITY)
 353         /*
 354          * For completeness we should put in equivalent code for code pages
 355          * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
 356          * doubt anyone wants Samba to behave differently from Win95 and WinNT
 357          * here. They both treat full width ascii characters as case senstive
 358          * filenames (ie. they don't do the work we do here).
 359          * JRA. 
 360          */
 361 
 362         if (lp_client_code_page () == KANJI_CODEPAGE)
 363         {
 364             /* Win95 treats full width ascii characters as case sensitive. */
 365             if (is_shift_jis (*s))
 366             {
 367                 if (is_sj_upper (s[0], s[1]))
 368                     s[1] = sj_tolower2 (s[1]);
 369                 s += 2;
 370             }
 371             else if (is_kana (*s))
 372             {
 373                 s++;
 374             }
 375             else
 376             {
 377                 if (isupper (*s))
 378                     *s = tolower (*s);
 379                 s++;
 380             }
 381         }
 382         else
 383 #endif /* KANJI_WIN95_COMPATIBILITY */
 384         {
 385             size_t skip = skip_multibyte_char (*s);
 386             if (skip != 0)
 387                 s += skip;
 388             else
 389             {
 390                 if (isupper (*s))
 391                     *s = tolower (*s);
 392                 s++;
 393             }
 394         }
 395     }
 396 }
 397 
 398 /*******************************************************************
 399   convert a string to upper case
 400 ********************************************************************/
 401 void
 402 strupper (char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 403 {
 404     while (*s)
 405     {
 406 #if !defined(KANJI_WIN95_COMPATIBILITY)
 407         /*
 408          * For completeness we should put in equivalent code for code pages
 409          * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
 410          * doubt anyone wants Samba to behave differently from Win95 and WinNT
 411          * here. They both treat full width ascii characters as case senstive
 412          * filenames (ie. they don't do the work we do here).
 413          * JRA. 
 414          */
 415 
 416         if (lp_client_code_page () == KANJI_CODEPAGE)
 417         {
 418             /* Win95 treats full width ascii characters as case sensitive. */
 419             if (is_shift_jis (*s))
 420             {
 421                 if (is_sj_lower (s[0], s[1]))
 422                     s[1] = sj_toupper2 (s[1]);
 423                 s += 2;
 424             }
 425             else if (is_kana (*s))
 426             {
 427                 s++;
 428             }
 429             else
 430             {
 431                 if (islower (*s))
 432                     *s = toupper (*s);
 433                 s++;
 434             }
 435         }
 436         else
 437 #endif /* KANJI_WIN95_COMPATIBILITY */
 438         {
 439             size_t skip = skip_multibyte_char (*s);
 440             if (skip != 0)
 441                 s += skip;
 442             else
 443             {
 444                 if (islower (*s))
 445                     *s = toupper (*s);
 446                 s++;
 447             }
 448         }
 449     }
 450 }
 451 
 452 #if 0
 453 /*******************************************************************
 454   convert a string to "normal" form
 455 ********************************************************************/
 456 void
 457 strnorm (char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 458 {
 459     extern int case_default;
 460     if (case_default == CASE_UPPER)
 461         strupper (s);
 462     else
 463         strlower (s);
 464 }
 465 
 466 /*******************************************************************
 467 check if a string is in "normal" case
 468 ********************************************************************/
 469 BOOL
 470 strisnormal (char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 471 {
 472     extern int case_default;
 473     if (case_default == CASE_UPPER)
 474         return (!strhaslower (s));
 475 
 476     return (!strhasupper (s));
 477 }
 478 #endif /* 0 */
 479 
 480 /****************************************************************************
 481   string replace
 482 ****************************************************************************/
 483 void
 484 string_replace (char *s, char oldc, char newc)
     /* [previous][next][first][last][top][bottom][index][help]  */
 485 {
 486     size_t skip;
 487     while (*s)
 488     {
 489         skip = skip_multibyte_char (*s);
 490         if (skip != 0)
 491             s += skip;
 492         else
 493         {
 494             if (oldc == *s)
 495                 *s = newc;
 496             s++;
 497         }
 498     }
 499 }
 500 
 501 
 502 /*******************************************************************
 503 skip past some strings in a buffer
 504 ********************************************************************/
 505 char *
 506 skip_string (char *buf, size_t n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 507 {
 508     while (n--)
 509         buf += strlen (buf) + 1;
 510     return (buf);
 511 }
 512 
 513 /*******************************************************************
 514  Count the number of characters in a string. Normally this will
 515  be the same as the number of bytes in a string for single byte strings,
 516  but will be different for multibyte.
 517  16.oct.98, jdblair@cobaltnet.com.
 518 ********************************************************************/
 519 
 520 size_t
 521 str_charnum (const char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 522 {
 523     size_t len = 0;
 524 
 525     while (*s != '\0')
 526     {
 527         int skip = skip_multibyte_char (*s);
 528         s += (skip ? skip : 1);
 529         len++;
 530     }
 531     return len;
 532 }
 533 
 534 /*******************************************************************
 535 trim the specified elements off the front and back of a string
 536 ********************************************************************/
 537 
 538 BOOL
 539 trim_string (char *s, const char *front, const char *back)
     /* [previous][next][first][last][top][bottom][index][help]  */
 540 {
 541     BOOL ret = False;
 542     size_t front_len = (front && *front) ? strlen (front) : 0;
 543     size_t back_len = (back && *back) ? strlen (back) : 0;
 544     size_t s_len;
 545 
 546     while (front_len && strncmp (s, front, front_len) == 0)
 547     {
 548         char *p = s;
 549         ret = True;
 550         while (1)
 551         {
 552             if (!(*p = p[front_len]))
 553                 break;
 554             p++;
 555         }
 556     }
 557 
 558     /*
 559      * We split out the multibyte code page
 560      * case here for speed purposes. Under a
 561      * multibyte code page we need to walk the
 562      * string forwards only and multiple times.
 563      * Thanks to John Blair for finding this
 564      * one. JRA.
 565      */
 566 
 567     if (back_len)
 568     {
 569         if (!is_multibyte_codepage ())
 570         {
 571             s_len = strlen (s);
 572             while ((s_len >= back_len) && (strncmp (s + s_len - back_len, back, back_len) == 0))
 573             {
 574                 ret = True;
 575                 s[s_len - back_len] = '\0';
 576                 s_len = strlen (s);
 577             }
 578         }
 579         else
 580         {
 581 
 582             /*
 583              * Multibyte code page case.
 584              * Keep going through the string, trying
 585              * to match the 'back' string with the end
 586              * of the string. If we get a match, truncate
 587              * 'back' off the end of the string and
 588              * go through the string again from the
 589              * start. Keep doing this until we have
 590              * gone through the string with no match
 591              * at the string end.
 592              */
 593 
 594             size_t mb_back_len = str_charnum (back);
 595             size_t mb_s_len = str_charnum (s);
 596 
 597             while (mb_s_len >= mb_back_len)
 598             {
 599                 size_t charcount = 0;
 600                 char *mbp = s;
 601 
 602                 while (charcount < (mb_s_len - mb_back_len))
 603                 {
 604                     size_t skip = skip_multibyte_char (*mbp);
 605                     mbp += (skip ? skip : 1);
 606                     charcount++;
 607                 }
 608 
 609                 /*
 610                  * mbp now points at mb_back_len multibyte
 611                  * characters from the end of s.
 612                  */
 613 
 614                 if (strcmp (mbp, back) == 0)
 615                 {
 616                     ret = True;
 617                     *mbp = '\0';
 618                     mb_s_len = str_charnum (s);
 619                     mbp = s;
 620                 }
 621                 else
 622                     break;
 623             }                   /* end while mb_s_len... */
 624         }                       /* end else .. */
 625     }                           /* end if back_len .. */
 626 
 627     return (ret);
 628 }
 629 
 630 #if 0
 631 /****************************************************************************
 632 does a string have any uppercase chars in it?
 633 ****************************************************************************/
 634 BOOL
 635 strhasupper (const char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 636 {
 637     while (*s)
 638     {
 639 #if !defined(KANJI_WIN95_COMPATIBILITY)
 640         /*
 641          * For completeness we should put in equivalent code for code pages
 642          * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
 643          * doubt anyone wants Samba to behave differently from Win95 and WinNT
 644          * here. They both treat full width ascii characters as case senstive
 645          * filenames (ie. they don't do the work we do here).
 646          * JRA. 
 647          */
 648 
 649         if (lp_client_code_page () == KANJI_CODEPAGE)
 650         {
 651             /* Win95 treats full width ascii characters as case sensitive. */
 652             if (is_shift_jis (*s))
 653                 s += 2;
 654             else if (is_kana (*s))
 655                 s++;
 656             else
 657             {
 658                 if (isupper (*s))
 659                     return (True);
 660                 s++;
 661             }
 662         }
 663         else
 664 #endif /* KANJI_WIN95_COMPATIBILITY */
 665         {
 666             size_t skip = skip_multibyte_char (*s);
 667             if (skip != 0)
 668                 s += skip;
 669             else
 670             {
 671                 if (isupper (*s))
 672                     return (True);
 673                 s++;
 674             }
 675         }
 676     }
 677     return (False);
 678 }
 679 
 680 
 681 /****************************************************************************
 682 does a string have any lowercase chars in it?
 683 ****************************************************************************/
 684 BOOL
 685 strhaslower (const char *s)
     /* [previous][next][first][last][top][bottom][index][help]  */
 686 {
 687     while (*s)
 688     {
 689 #if !defined(KANJI_WIN95_COMPATIBILITY)
 690         /*
 691          * For completeness we should put in equivalent code for code pages
 692          * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
 693          * doubt anyone wants Samba to behave differently from Win95 and WinNT
 694          * here. They both treat full width ascii characters as case senstive
 695          * filenames (ie. they don't do the work we do here).
 696          * JRA. 
 697          */
 698 
 699         if (lp_client_code_page () == KANJI_CODEPAGE)
 700         {
 701             /* Win95 treats full width ascii characters as case sensitive. */
 702             if (is_shift_jis (*s))
 703             {
 704                 if (is_sj_upper (s[0], s[1]))
 705                     return (True);
 706                 if (is_sj_lower (s[0], s[1]))
 707                     return (True);
 708                 s += 2;
 709             }
 710             else if (is_kana (*s))
 711             {
 712                 s++;
 713             }
 714             else
 715             {
 716                 if (islower (*s))
 717                     return (True);
 718                 s++;
 719             }
 720         }
 721         else
 722 #endif /* KANJI_WIN95_COMPATIBILITY */
 723         {
 724             size_t skip = skip_multibyte_char (*s);
 725             if (skip != 0)
 726                 s += skip;
 727             else
 728             {
 729                 if (islower (*s))
 730                     return (True);
 731                 s++;
 732             }
 733         }
 734     }
 735     return (False);
 736 }
 737 #endif /*0 */
 738 
 739 /****************************************************************************
 740 find the number of chars in a string
 741 ****************************************************************************/
 742 size_t
 743 count_chars (const char *s, char c)
     /* [previous][next][first][last][top][bottom][index][help]  */
 744 {
 745     size_t count = 0;
 746 
 747 #if !defined(KANJI_WIN95_COMPATIBILITY)
 748     /*
 749      * For completeness we should put in equivalent code for code pages
 750      * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
 751      * doubt anyone wants Samba to behave differently from Win95 and WinNT
 752      * here. They both treat full width ascii characters as case senstive
 753      * filenames (ie. they don't do the work we do here).
 754      * JRA. 
 755      */
 756 
 757     if (lp_client_code_page () == KANJI_CODEPAGE)
 758     {
 759         /* Win95 treats full width ascii characters as case sensitive. */
 760         while (*s)
 761         {
 762             if (is_shift_jis (*s))
 763                 s += 2;
 764             else
 765             {
 766                 if (*s == c)
 767                     count++;
 768                 s++;
 769             }
 770         }
 771     }
 772     else
 773 #endif /* KANJI_WIN95_COMPATIBILITY */
 774     {
 775         while (*s)
 776         {
 777             size_t skip = skip_multibyte_char (*s);
 778             if (skip != 0)
 779                 s += skip;
 780             else
 781             {
 782                 if (*s == c)
 783                     count++;
 784                 s++;
 785             }
 786         }
 787     }
 788     return (count);
 789 }
 790 
 791 
 792 
 793 /*******************************************************************
 794 safe string copy into a known length string. maxlength does not
 795 include the terminating zero.
 796 ********************************************************************/
 797 char *
 798 safe_strcpy (char *dest, const char *src, size_t maxlength)
     /* [previous][next][first][last][top][bottom][index][help]  */
 799 {
 800     size_t len;
 801 
 802     if (!dest)
 803     {
 804         DEBUG (0, ("ERROR: NULL dest in safe_strcpy\n"));
 805         return NULL;
 806     }
 807 
 808     if (!src)
 809     {
 810         *dest = 0;
 811         return dest;
 812     }
 813 
 814     len = strlen (src);
 815 
 816     if (len > maxlength)
 817     {
 818         DEBUG (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
 819                    (int) (len - maxlength), src));
 820         len = maxlength;
 821     }
 822 
 823     memcpy (dest, src, len);
 824     dest[len] = 0;
 825     return dest;
 826 }
 827 
 828 /*******************************************************************
 829 safe string cat into a string. maxlength does not
 830 include the terminating zero.
 831 ********************************************************************/
 832 char *
 833 safe_strcat (char *dest, const char *src, size_t maxlength)
     /* [previous][next][first][last][top][bottom][index][help]  */
 834 {
 835     size_t src_len, dest_len;
 836 
 837     if (!dest)
 838     {
 839         DEBUG (0, ("ERROR: NULL dest in safe_strcat\n"));
 840         return NULL;
 841     }
 842 
 843     if (!src)
 844     {
 845         return dest;
 846     }
 847 
 848     src_len = strlen (src);
 849     dest_len = strlen (dest);
 850 
 851     if (src_len + dest_len > maxlength)
 852     {
 853         DEBUG (0, ("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
 854                    (int) (src_len + dest_len - maxlength), src));
 855         src_len = maxlength - dest_len;
 856     }
 857 
 858     memcpy (&dest[dest_len], src, src_len);
 859     dest[dest_len + src_len] = 0;
 860     return dest;
 861 }
 862 
 863 /****************************************************************************
 864 this is a safer strcpy(), meant to prevent core dumps when nasty things happen
 865 ****************************************************************************/
 866 char *
 867 StrCpy (char *dest, const char *src)
     /* [previous][next][first][last][top][bottom][index][help]  */
 868 {
 869     char *d = dest;
 870 
 871     /* I don't want to get lazy with these ... */
 872     SMB_ASSERT (dest && src);
 873 
 874     if (!dest)
 875         return (NULL);
 876     if (!src)
 877     {
 878         *dest = 0;
 879         return (dest);
 880     }
 881     while ((*d++ = *src++));
 882     return (dest);
 883 }
 884 
 885 /****************************************************************************
 886 like strncpy but always null terminates. Make sure there is room!
 887 ****************************************************************************/
 888 char *
 889 StrnCpy (char *dest, const char *src, size_t n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 890 {
 891     char *d = dest;
 892     if (!dest)
 893         return (NULL);
 894     if (!src)
 895     {
 896         *dest = 0;
 897         return (dest);
 898     }
 899     while (n-- && (*d++ = *src++));
 900     *d = 0;
 901     return (dest);
 902 }
 903 
 904 #if 0
 905 /****************************************************************************
 906 like strncpy but copies up to the character marker.  always null terminates.
 907 returns a pointer to the character marker in the source string (src).
 908 ****************************************************************************/
 909 char *
 910 strncpyn (char *dest, const char *src, size_t n, char c)
     /* [previous][next][first][last][top][bottom][index][help]  */
 911 {
 912     char *p;
 913     size_t str_len;
 914 
 915     p = strchr (src, c);
 916     if (p == NULL)
 917     {
 918         DEBUG (5, ("strncpyn: separator character (%c) not found\n", c));
 919         return NULL;
 920     }
 921 
 922     str_len = PTR_DIFF (p, src);
 923     strncpy (dest, src, MIN (n, str_len));
 924     dest[str_len] = '\0';
 925 
 926     return p;
 927 }
 928 
 929 
 930 /*************************************************************
 931  Routine to get hex characters and turn them into a 16 byte array.
 932  the array can be variable length, and any non-hex-numeric
 933  characters are skipped.  "0xnn" or "0Xnn" is specially catered
 934  for.
 935 
 936  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
 937 
 938 **************************************************************/
 939 size_t
 940 strhex_to_str (char *p, size_t len, const char *strhex)
     /* [previous][next][first][last][top][bottom][index][help]  */
 941 {
 942     size_t i;
 943     size_t num_chars = 0;
 944     unsigned char lonybble, hinybble;
 945     char *hexchars = "0123456789ABCDEF";
 946     char *p1 = NULL, *p2 = NULL;
 947 
 948     for (i = 0; i < len && strhex[i] != 0; i++)
 949     {
 950         if (strnequal (hexchars, "0x", 2))
 951         {
 952             i++;                /* skip two chars */
 953             continue;
 954         }
 955 
 956         if (!(p1 = strchr (hexchars, toupper (strhex[i]))))
 957         {
 958             break;
 959         }
 960 
 961         i++;                    /* next hex digit */
 962 
 963         if (!(p2 = strchr (hexchars, toupper (strhex[i]))))
 964         {
 965             break;
 966         }
 967 
 968         /* get the two nybbles */
 969         hinybble = PTR_DIFF (p1, hexchars);
 970         lonybble = PTR_DIFF (p2, hexchars);
 971 
 972         p[num_chars] = (hinybble << 4) | lonybble;
 973         num_chars++;
 974 
 975         p1 = NULL;
 976         p2 = NULL;
 977     }
 978     return num_chars;
 979 }
 980 
 981 /****************************************************************************
 982 check if a string is part of a list
 983 ****************************************************************************/
 984 BOOL
 985 in_list (char *s, char *list, BOOL casesensitive)
     /* [previous][next][first][last][top][bottom][index][help]  */
 986 {
 987     pstring tok;
 988     char *p = list;
 989 
 990     if (!list)
 991         return (False);
 992 
 993     while (next_token (&p, tok, LIST_SEP, sizeof (tok)))
 994     {
 995         if (casesensitive)
 996         {
 997             if (strcmp (tok, s) == 0)
 998                 return (True);
 999         }
1000         else
1001         {
1002             if (StrCaseCmp (tok, s) == 0)
1003                 return (True);
1004         }
1005     }
1006     return (False);
1007 }
1008 #endif /*0 */
1009 
1010 /* this is used to prevent lots of mallocs of size 1 */
1011 static char *null_string = NULL;
1012 
1013 /****************************************************************************
1014 set a string value, allocing the space for the string
1015 ****************************************************************************/
1016 BOOL
1017 string_init (char **dest, const char *src)
     /* [previous][next][first][last][top][bottom][index][help]  */
1018 {
1019     size_t l;
1020     if (!src)
1021         src = "";
1022 
1023     l = strlen (src);
1024 
1025     if (l == 0)
1026     {
1027         if (!null_string)
1028         {
1029             if ((null_string = (char *) malloc (1)) == NULL)
1030             {
1031                 DEBUG (0, ("string_init: malloc fail for null_string.\n"));
1032                 return False;
1033             }
1034             *null_string = 0;
1035         }
1036         *dest = null_string;
1037     }
1038     else
1039     {
1040         (*dest) = (char *) malloc (l + 1);
1041         if ((*dest) == NULL)
1042         {
1043             DEBUG (0, ("Out of memory in string_init\n"));
1044             return False;
1045         }
1046 
1047         pstrcpy (*dest, src);
1048     }
1049     return (True);
1050 }
1051 
1052 /****************************************************************************
1053 free a string value
1054 ****************************************************************************/
1055 void
1056 string_free (char **s)
     /* [previous][next][first][last][top][bottom][index][help]  */
1057 {
1058     if (!s || !(*s))
1059         return;
1060     if (*s == null_string)
1061         *s = NULL;
1062     if (*s)
1063         free (*s);
1064     *s = NULL;
1065 }
1066 
1067 /****************************************************************************
1068 set a string value, allocing the space for the string, and deallocating any 
1069 existing space
1070 ****************************************************************************/
1071 BOOL
1072 string_set (char **dest, const char *src)
     /* [previous][next][first][last][top][bottom][index][help]  */
1073 {
1074     string_free (dest);
1075 
1076     return (string_init (dest, src));
1077 }
1078 
1079 
1080 /****************************************************************************
1081 substitute a string for a pattern in another string. Make sure there is 
1082 enough room!
1083 
1084 This routine looks for pattern in s and replaces it with 
1085 insert. It may do multiple replacements.
1086 
1087 any of " ; ' or ` in the insert string are replaced with _
1088 ****************************************************************************/
1089 void
1090 string_sub (char *s, const char *pattern, const char *insert)
     /* [previous][next][first][last][top][bottom][index][help]  */
1091 {
1092     char *p;
1093     size_t ls, lp, li, i;
1094 
1095     if (!insert || !pattern || !s)
1096         return;
1097 
1098     ls = strlen (s);
1099     lp = strlen (pattern);
1100     li = strlen (insert);
1101 
1102     if (!*pattern)
1103         return;
1104 
1105     while (lp <= ls && (p = strstr (s, pattern)))
1106     {
1107         memmove (p + li, p + lp, ls + 1 - (PTR_DIFF (p, s) + lp));
1108         for (i = 0; i < li; i++)
1109         {
1110             switch (insert[i])
1111             {
1112             case '`':
1113             case '"':
1114             case '\'':
1115             case ';':
1116                 p[i] = '_';
1117                 break;
1118             default:
1119                 p[i] = insert[i];
1120             }
1121         }
1122         s = p + li;
1123         ls += (li - lp);
1124     }
1125 }
1126 
1127 #if 0
1128 /****************************************************************************
1129 similar to string_sub() but allows for any character to be substituted. 
1130 Use with caution!
1131 ****************************************************************************/
1132 void
1133 all_string_sub (char *s, const char *pattern, const char *insert)
     /* [previous][next][first][last][top][bottom][index][help]  */
1134 {
1135     char *p;
1136     size_t ls, lp, li;
1137 
1138     if (!insert || !pattern || !s)
1139         return;
1140 
1141     ls = strlen (s);
1142     lp = strlen (pattern);
1143     li = strlen (insert);
1144 
1145     if (!*pattern)
1146         return;
1147 
1148     while (lp <= ls && (p = strstr (s, pattern)))
1149     {
1150         memmove (p + li, p + lp, ls + 1 - (PTR_DIFF (p, s) + lp));
1151         memcpy (p, insert, li);
1152         s = p + li;
1153         ls += (li - lp);
1154     }
1155 }
1156 
1157 
1158 /****************************************************************************
1159  splits out the front and back at a separator.
1160 ****************************************************************************/
1161 void
1162 split_at_last_component (char *path, char *front, char sep, char *back)
     /* [previous][next][first][last][top][bottom][index][help]  */
1163 {
1164     char *p = strrchr (path, sep);
1165 
1166     if (p != NULL)
1167     {
1168         *p = 0;
1169     }
1170     if (front != NULL)
1171     {
1172         pstrcpy (front, path);
1173     }
1174     if (p != NULL)
1175     {
1176         if (back != NULL)
1177         {
1178             pstrcpy (back, p + 1);
1179         }
1180         *p = '\\';
1181     }
1182     else
1183     {
1184         if (back != NULL)
1185         {
1186             back[0] = 0;
1187         }
1188     }
1189 }
1190 #endif /*0 */

/* [previous][next][first][last][top][bottom][index][help]  */