07a058925dd07426780d639f9e8cb1fd6e29b7f8
[samba.git] / source3 / lib / util_str.c
1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4
5    Copyright (C) Andrew Tridgell 1992-2001
6    Copyright (C) Simo Sorce      2001-2002
7    Copyright (C) Martin Pool     2003
8    Copyright (C) James Peach     2006
9    Copyright (C) Jeremy Allison  1992-2007
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26
27 const char toupper_ascii_fast_table[128] = {
28         0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
29         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
30         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
31         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
32         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
33         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
34         0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
35         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
36 };
37
38 /**
39  * Case insensitive string compararison.
40  *
41  * iconv does not directly give us a way to compare strings in
42  * arbitrary unix character sets -- all we can is convert and then
43  * compare.  This is expensive.
44  *
45  * As an optimization, we do a first pass that considers only the
46  * prefix of the strings that is entirely 7-bit.  Within this, we
47  * check whether they have the same value.
48  *
49  * Hopefully this will often give the answer without needing to copy.
50  * In particular it should speed comparisons to literal ascii strings
51  * or comparisons of strings that are "obviously" different.
52  *
53  * If we find a non-ascii character we fall back to converting via
54  * iconv.
55  *
56  * This should never be slower than convering the whole thing, and
57  * often faster.
58  *
59  * A different optimization would be to compare for bitwise equality
60  * in the binary encoding.  (It would be possible thought hairy to do
61  * both simultaneously.)  But in that case if they turn out to be
62  * different, we'd need to restart the whole thing.
63  *
64  * Even better is to implement strcasecmp for each encoding and use a
65  * function pointer.
66  **/
67 int StrCaseCmp(const char *s, const char *t)
68 {
69
70         const char *ps, *pt;
71         size_t size;
72         smb_ucs2_t *buffer_s, *buffer_t;
73         int ret;
74
75         for (ps = s, pt = t; ; ps++, pt++) {
76                 char us, ut;
77
78                 if (!*ps && !*pt)
79                         return 0; /* both ended */
80                 else if (!*ps)
81                         return -1; /* s is a prefix */
82                 else if (!*pt)
83                         return +1; /* t is a prefix */
84                 else if ((*ps & 0x80) || (*pt & 0x80))
85                         /* not ascii anymore, do it the hard way
86                          * from here on in */
87                         break;
88
89                 us = toupper_ascii_fast(*ps);
90                 ut = toupper_ascii_fast(*pt);
91                 if (us == ut)
92                         continue;
93                 else if (us < ut)
94                         return -1;
95                 else if (us > ut)
96                         return +1;
97         }
98
99         if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
100                 return strcmp(ps, pt);
101                 /* Not quite the right answer, but finding the right one
102                    under this failure case is expensive, and it's pretty
103                    close */
104         }
105
106         if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
107                 TALLOC_FREE(buffer_s);
108                 return strcmp(ps, pt);
109                 /* Not quite the right answer, but finding the right one
110                    under this failure case is expensive, and it's pretty
111                    close */
112         }
113
114         ret = strcasecmp_w(buffer_s, buffer_t);
115         TALLOC_FREE(buffer_s);
116         TALLOC_FREE(buffer_t);
117         return ret;
118 }
119
120
121 /**
122  Case insensitive string compararison, length limited.
123 **/
124 int StrnCaseCmp(const char *s, const char *t, size_t len)
125 {
126         size_t n = 0;
127         const char *ps, *pt;
128         size_t size;
129         smb_ucs2_t *buffer_s, *buffer_t;
130         int ret;
131
132         for (ps = s, pt = t; n < len ; ps++, pt++, n++) {
133                 char us, ut;
134
135                 if (!*ps && !*pt)
136                         return 0; /* both ended */
137                 else if (!*ps)
138                         return -1; /* s is a prefix */
139                 else if (!*pt)
140                         return +1; /* t is a prefix */
141                 else if ((*ps & 0x80) || (*pt & 0x80))
142                         /* not ascii anymore, do it the
143                          * hard way from here on in */
144                         break;
145
146                 us = toupper_ascii_fast(*ps);
147                 ut = toupper_ascii_fast(*pt);
148                 if (us == ut)
149                         continue;
150                 else if (us < ut)
151                         return -1;
152                 else if (us > ut)
153                         return +1;
154         }
155
156         if (n == len) {
157                 return 0;
158         }
159
160         if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
161                 return strncmp(ps, pt, len-n);
162                 /* Not quite the right answer, but finding the right one
163                    under this failure case is expensive,
164                    and it's pretty close */
165         }
166
167         if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
168                 TALLOC_FREE(buffer_s);
169                 return strncmp(ps, pt, len-n);
170                 /* Not quite the right answer, but finding the right one
171                    under this failure case is expensive,
172                    and it's pretty close */
173         }
174
175         ret = strncasecmp_w(buffer_s, buffer_t, len-n);
176         TALLOC_FREE(buffer_s);
177         TALLOC_FREE(buffer_t);
178         return ret;
179 }
180
181 /**
182  * Compare 2 strings.
183  *
184  * @note The comparison is case-insensitive.
185  **/
186 bool strequal(const char *s1, const char *s2)
187 {
188         if (s1 == s2)
189                 return(true);
190         if (!s1 || !s2)
191                 return(false);
192
193         return(StrCaseCmp(s1,s2)==0);
194 }
195
196 /**
197  * Compare 2 strings up to and including the nth char.
198  *
199  * @note The comparison is case-insensitive.
200  **/
201 bool strnequal(const char *s1,const char *s2,size_t n)
202 {
203         if (s1 == s2)
204                 return(true);
205         if (!s1 || !s2 || !n)
206                 return(false);
207
208         return(StrnCaseCmp(s1,s2,n)==0);
209 }
210
211 /**
212  Convert a string to "normal" form.
213 **/
214
215 void strnorm(char *s, int case_default)
216 {
217         if (case_default == CASE_UPPER)
218                 strupper_m(s);
219         else
220                 strlower_m(s);
221 }
222
223 /**
224  *  Skip past some strings in a buffer - old version - no checks.
225  *  **/
226
227 char *push_skip_string(char *buf)
228 {
229         buf += strlen(buf) + 1;
230         return(buf);
231 }
232
233 /**
234  Skip past a string in a buffer. Buffer may not be
235  null terminated. end_ptr points to the first byte after
236  then end of the buffer.
237 **/
238
239 char *skip_string(const char *base, size_t len, char *buf)
240 {
241         const char *end_ptr = base + len;
242
243         if (end_ptr < base || !base || !buf || buf >= end_ptr) {
244                 return NULL;
245         }
246
247         /* Skip the string */
248         while (*buf) {
249                 buf++;
250                 if (buf >= end_ptr) {
251                         return NULL;
252                 }
253         }
254         /* Skip the '\0' */
255         buf++;
256         return buf;
257 }
258
259 /**
260  Count the number of characters in a string. Normally this will
261  be the same as the number of bytes in a string for single byte strings,
262  but will be different for multibyte.
263 **/
264
265 size_t str_charnum(const char *s)
266 {
267         size_t ret, converted_size;
268         smb_ucs2_t *tmpbuf2 = NULL;
269         if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
270                 return 0;
271         }
272         ret = strlen_w(tmpbuf2);
273         TALLOC_FREE(tmpbuf2);
274         return ret;
275 }
276
277 bool trim_char(char *s,char cfront,char cback)
278 {
279         bool ret = false;
280         char *ep;
281         char *fp = s;
282
283         /* Ignore null or empty strings. */
284         if (!s || (s[0] == '\0'))
285                 return false;
286
287         if (cfront) {
288                 while (*fp && *fp == cfront)
289                         fp++;
290                 if (!*fp) {
291                         /* We ate the string. */
292                         s[0] = '\0';
293                         return true;
294                 }
295                 if (fp != s)
296                         ret = true;
297         }
298
299         ep = fp + strlen(fp) - 1;
300         if (cback) {
301                 /* Attempt ascii only. Bail for mb strings. */
302                 while ((ep >= fp) && (*ep == cback)) {
303                         ret = true;
304                         if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
305                                 /* Could be mb... bail back to tim_string. */
306                                 char fs[2], bs[2];
307                                 if (cfront) {
308                                         fs[0] = cfront;
309                                         fs[1] = '\0';
310                                 }
311                                 bs[0] = cback;
312                                 bs[1] = '\0';
313                                 return trim_string(s, cfront ? fs : NULL, bs);
314                         } else {
315                                 ep--;
316                         }
317                 }
318                 if (ep < fp) {
319                         /* We ate the string. */
320                         s[0] = '\0';
321                         return true;
322                 }
323         }
324
325         ep[1] = '\0';
326         memmove(s, fp, ep-fp+2);
327         return ret;
328 }
329
330 /**
331  Safe string copy into a known length string. maxlength does not
332  include the terminating zero.
333 **/
334
335 char *safe_strcpy_fn(char *dest,
336                      const char *src,
337                      size_t maxlength)
338 {
339         size_t len;
340
341         if (!dest) {
342                 smb_panic("ERROR: NULL dest in safe_strcpy");
343         }
344
345         if (!src) {
346                 *dest = 0;
347                 return dest;
348         }
349
350         len = strnlen(src, maxlength+1);
351
352         if (len > maxlength) {
353                 DEBUG(0,("ERROR: string overflow by "
354                         "%lu (%lu - %lu) in safe_strcpy [%.50s]\n",
355                          (unsigned long)(len-maxlength), (unsigned long)len,
356                          (unsigned long)maxlength, src));
357                 len = maxlength;
358         }
359
360         memmove(dest, src, len);
361         dest[len] = 0;
362         return dest;
363 }
364
365 /**
366  Safe string cat into a string. maxlength does not
367  include the terminating zero.
368 **/
369 char *safe_strcat_fn(char *dest,
370                      const char *src,
371                      size_t maxlength)
372 {
373         size_t src_len, dest_len;
374
375         if (!dest) {
376                 smb_panic("ERROR: NULL dest in safe_strcat");
377         }
378
379         if (!src)
380                 return dest;
381
382         src_len = strnlen(src, maxlength + 1);
383         dest_len = strnlen(dest, maxlength + 1);
384
385         if (src_len + dest_len > maxlength) {
386                 DEBUG(0,("ERROR: string overflow by %d "
387                         "in safe_strcat [%.50s]\n",
388                          (int)(src_len + dest_len - maxlength), src));
389                 if (maxlength > dest_len) {
390                         memcpy(&dest[dest_len], src, maxlength - dest_len);
391                 }
392                 dest[maxlength] = 0;
393                 return NULL;
394         }
395
396         memcpy(&dest[dest_len], src, src_len);
397         dest[dest_len + src_len] = 0;
398         return dest;
399 }
400
401 /**
402  Like strncpy but always null terminates. Make sure there is room!
403  The variable n should always be one less than the available size.
404 **/
405 char *StrnCpy(char *dest,const char *src,size_t n)
406 {
407         char *d = dest;
408
409         if (!dest) {
410                 smb_panic("ERROR: NULL dest in StrnCpy");
411         }
412
413         if (!src) {
414                 *dest = 0;
415                 return(dest);
416         }
417
418         while (n-- && (*d = *src)) {
419                 d++;
420                 src++;
421         }
422
423         *d = 0;
424         return(dest);
425 }
426
427 /**
428  Check if a string is part of a list.
429 **/
430
431 bool in_list(const char *s, const char *list, bool casesensitive)
432 {
433         char *tok = NULL;
434         bool ret = false;
435         TALLOC_CTX *frame;
436
437         if (!list) {
438                 return false;
439         }
440
441         frame = talloc_stackframe();
442         while (next_token_talloc(frame, &list, &tok,LIST_SEP)) {
443                 if (casesensitive) {
444                         if (strcmp(tok,s) == 0) {
445                                 ret = true;
446                                 break;
447                         }
448                 } else {
449                         if (StrCaseCmp(tok,s) == 0) {
450                                 ret = true;
451                                 break;
452                         }
453                 }
454         }
455         TALLOC_FREE(frame);
456         return ret;
457 }
458
459 /* this is used to prevent lots of mallocs of size 1 */
460 static const char null_string[] = "";
461
462 /**
463  Set a string value, allocing the space for the string
464 **/
465
466 static bool string_init(char **dest,const char *src)
467 {
468         size_t l;
469
470         if (!src)
471                 src = "";
472
473         l = strlen(src);
474
475         if (l == 0) {
476                 *dest = CONST_DISCARD(char*, null_string);
477         } else {
478                 (*dest) = SMB_STRDUP(src);
479                 if ((*dest) == NULL) {
480                         DEBUG(0,("Out of memory in string_init\n"));
481                         return false;
482                 }
483         }
484         return(true);
485 }
486
487 /**
488  Free a string value.
489 **/
490
491 void string_free(char **s)
492 {
493         if (!s || !(*s))
494                 return;
495         if (*s == null_string)
496                 *s = NULL;
497         SAFE_FREE(*s);
498 }
499
500 /**
501  Set a string value, deallocating any existing space, and allocing the space
502  for the string
503 **/
504
505 bool string_set(char **dest,const char *src)
506 {
507         string_free(dest);
508         return(string_init(dest,src));
509 }
510
511 void fstring_sub(char *s,const char *pattern,const char *insert)
512 {
513         string_sub(s, pattern, insert, sizeof(fstring));
514 }
515
516 /**
517  Similar to string_sub2, but it will accept only allocated strings
518  and may realloc them so pay attention at what you pass on no
519  pointers inside strings, no const may be passed
520  as string.
521 **/
522
523 char *realloc_string_sub2(char *string,
524                         const char *pattern,
525                         const char *insert,
526                         bool remove_unsafe_characters,
527                         bool allow_trailing_dollar)
528 {
529         char *p, *in;
530         char *s;
531         ssize_t ls,lp,li,ld, i;
532
533         if (!insert || !pattern || !*pattern || !string || !*string)
534                 return NULL;
535
536         s = string;
537
538         in = SMB_STRDUP(insert);
539         if (!in) {
540                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
541                 return NULL;
542         }
543         ls = (ssize_t)strlen(s);
544         lp = (ssize_t)strlen(pattern);
545         li = (ssize_t)strlen(insert);
546         ld = li - lp;
547         for (i=0;i<li;i++) {
548                 switch (in[i]) {
549                         case '$':
550                                 /* allow a trailing $
551                                  * (as in machine accounts) */
552                                 if (allow_trailing_dollar && (i == li - 1 )) {
553                                         break;
554                                 }
555                         case '`':
556                         case '"':
557                         case '\'':
558                         case ';':
559                         case '%':
560                         case '\r':
561                         case '\n':
562                                 if ( remove_unsafe_characters ) {
563                                         in[i] = '_';
564                                         break;
565                                 }
566                         default:
567                                 /* ok */
568                                 break;
569                 }
570         }
571
572         while ((p = strstr_m(s,pattern))) {
573                 if (ld > 0) {
574                         int offset = PTR_DIFF(s,string);
575                         string = (char *)SMB_REALLOC(string, ls + ld + 1);
576                         if (!string) {
577                                 DEBUG(0, ("realloc_string_sub: "
578                                         "out of memory!\n"));
579                                 SAFE_FREE(in);
580                                 return NULL;
581                         }
582                         p = string + offset + (p - s);
583                 }
584                 if (li != lp) {
585                         memmove(p+li,p+lp,strlen(p+lp)+1);
586                 }
587                 memcpy(p, in, li);
588                 s = p + li;
589                 ls += ld;
590         }
591         SAFE_FREE(in);
592         return string;
593 }
594
595 char *realloc_string_sub(char *string,
596                         const char *pattern,
597                         const char *insert)
598 {
599         return realloc_string_sub2(string, pattern, insert, true, false);
600 }
601
602 /*
603  * Internal guts of talloc_string_sub and talloc_all_string_sub.
604  * talloc version of string_sub2.
605  */
606
607 char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
608                         const char *pattern,
609                         const char *insert,
610                         bool remove_unsafe_characters,
611                         bool replace_once,
612                         bool allow_trailing_dollar)
613 {
614         char *p, *in;
615         char *s;
616         char *string;
617         ssize_t ls,lp,li,ld, i;
618
619         if (!insert || !pattern || !*pattern || !src) {
620                 return NULL;
621         }
622
623         string = talloc_strdup(mem_ctx, src);
624         if (string == NULL) {
625                 DEBUG(0, ("talloc_string_sub2: "
626                         "talloc_strdup failed\n"));
627                 return NULL;
628         }
629
630         s = string;
631
632         in = SMB_STRDUP(insert);
633         if (!in) {
634                 DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
635                 return NULL;
636         }
637         ls = (ssize_t)strlen(s);
638         lp = (ssize_t)strlen(pattern);
639         li = (ssize_t)strlen(insert);
640         ld = li - lp;
641
642         for (i=0;i<li;i++) {
643                 switch (in[i]) {
644                         case '$':
645                                 /* allow a trailing $
646                                  * (as in machine accounts) */
647                                 if (allow_trailing_dollar && (i == li - 1 )) {
648                                         break;
649                                 }
650                         case '`':
651                         case '"':
652                         case '\'':
653                         case ';':
654                         case '%':
655                         case '\r':
656                         case '\n':
657                                 if (remove_unsafe_characters) {
658                                         in[i] = '_';
659                                         break;
660                                 }
661                         default:
662                                 /* ok */
663                                 break;
664                 }
665         }
666
667         while ((p = strstr_m(s,pattern))) {
668                 if (ld > 0) {
669                         int offset = PTR_DIFF(s,string);
670                         string = (char *)TALLOC_REALLOC(mem_ctx, string,
671                                                         ls + ld + 1);
672                         if (!string) {
673                                 DEBUG(0, ("talloc_string_sub: out of "
674                                           "memory!\n"));
675                                 SAFE_FREE(in);
676                                 return NULL;
677                         }
678                         p = string + offset + (p - s);
679                 }
680                 if (li != lp) {
681                         memmove(p+li,p+lp,strlen(p+lp)+1);
682                 }
683                 memcpy(p, in, li);
684                 s = p + li;
685                 ls += ld;
686
687                 if (replace_once) {
688                         break;
689                 }
690         }
691         SAFE_FREE(in);
692         return string;
693 }
694
695 /* Same as string_sub, but returns a talloc'ed string */
696
697 char *talloc_string_sub(TALLOC_CTX *mem_ctx,
698                         const char *src,
699                         const char *pattern,
700                         const char *insert)
701 {
702         return talloc_string_sub2(mem_ctx, src, pattern, insert,
703                         true, false, false);
704 }
705
706 char *talloc_all_string_sub(TALLOC_CTX *ctx,
707                                 const char *src,
708                                 const char *pattern,
709                                 const char *insert)
710 {
711         return talloc_string_sub2(ctx, src, pattern, insert,
712                         false, false, false);
713 }
714
715 /**
716  Write an octal as a string.
717 **/
718
719 char *octal_string(int i)
720 {
721         char *result;
722         if (i == -1) {
723                 result = talloc_strdup(talloc_tos(), "-1");
724         }
725         else {
726                 result = talloc_asprintf(talloc_tos(), "0%o", i);
727         }
728         SMB_ASSERT(result != NULL);
729         return result;
730 }
731
732
733 /**
734  Truncate a string at a specified length.
735 **/
736
737 char *string_truncate(char *s, unsigned int length)
738 {
739         if (s && strlen(s) > length)
740                 s[length] = 0;
741         return s;
742 }
743
744
745 /***********************************************************************
746  Return the equivalent of doing strrchr 'n' times - always going
747  backwards.
748 ***********************************************************************/
749
750 char *strnrchr_m(const char *s, char c, unsigned int n)
751 {
752         smb_ucs2_t *ws = NULL;
753         char *s2 = NULL;
754         smb_ucs2_t *p;
755         char *ret;
756         size_t converted_size;
757
758         if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
759                 /* Too hard to try and get right. */
760                 return NULL;
761         }
762         p = strnrchr_w(ws, UCS2_CHAR(c), n);
763         if (!p) {
764                 TALLOC_FREE(ws);
765                 return NULL;
766         }
767         *p = 0;
768         if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
769                 TALLOC_FREE(ws);
770                 /* Too hard to try and get right. */
771                 return NULL;
772         }
773         ret = (char *)(s+strlen(s2));
774         TALLOC_FREE(ws);
775         TALLOC_FREE(s2);
776         return ret;
777 }
778
779 static bool unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
780 {
781         size_t size;
782         smb_ucs2_t *buffer = NULL;
783         bool ret;
784
785         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
786                                    (void **)(void *)&buffer, &size))
787         {
788                 smb_panic("failed to create UCS2 buffer");
789         }
790         if (!strlower_w(buffer) && (dest == src)) {
791                 TALLOC_FREE(buffer);
792                 return srclen;
793         }
794         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
795         TALLOC_FREE(buffer);
796         return ret;
797 }
798
799
800 /**
801  Convert a string to lower case.
802 **/
803
804 void strlower_m(char *s)
805 {
806         size_t len;
807         int errno_save;
808
809         /* this is quite a common operation, so we want it to be
810            fast. We optimise for the ascii case, knowing that all our
811            supported multi-byte character sets are ascii-compatible
812            (ie. they match for the first 128 chars) */
813
814         while (*s && !(((unsigned char)s[0]) & 0x80)) {
815                 *s = tolower_ascii((unsigned char)*s);
816                 s++;
817         }
818
819         if (!*s)
820                 return;
821
822         /* I assume that lowercased string takes the same number of bytes
823          * as source string even in UTF-8 encoding. (VIV) */
824         len = strlen(s) + 1;
825         errno_save = errno;
826         errno = 0;
827         unix_strlower(s,len,s,len);
828         /* Catch mb conversion errors that may not terminate. */
829         if (errno)
830                 s[len-1] = '\0';
831         errno = errno_save;
832 }
833
834 static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
835 {
836         size_t size;
837         smb_ucs2_t *buffer;
838         bool ret;
839
840         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
841                 return (size_t)-1;
842         }
843
844         if (!strupper_w(buffer) && (dest == src)) {
845                 TALLOC_FREE(buffer);
846                 return srclen;
847         }
848
849         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
850         TALLOC_FREE(buffer);
851         return ret;
852 }
853
854 /**
855  Convert a string to upper case.
856 **/
857
858 void strupper_m(char *s)
859 {
860         size_t len;
861         int errno_save;
862
863         /* this is quite a common operation, so we want it to be
864            fast. We optimise for the ascii case, knowing that all our
865            supported multi-byte character sets are ascii-compatible
866            (ie. they match for the first 128 chars) */
867
868         while (*s && !(((unsigned char)s[0]) & 0x80)) {
869                 *s = toupper_ascii_fast((unsigned char)*s);
870                 s++;
871         }
872
873         if (!*s)
874                 return;
875
876         /* I assume that lowercased string takes the same number of bytes
877          * as source string even in multibyte encoding. (VIV) */
878         len = strlen(s) + 1;
879         errno_save = errno;
880         errno = 0;
881         unix_strupper(s,len,s,len);
882         /* Catch mb conversion errors that may not terminate. */
883         if (errno)
884                 s[len-1] = '\0';
885         errno = errno_save;
886 }
887
888 /**
889  Just a typesafety wrapper for snprintf into a fstring.
890 **/
891
892 int fstr_sprintf(fstring s, const char *fmt, ...)
893 {
894         va_list ap;
895         int ret;
896
897         va_start(ap, fmt);
898         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
899         va_end(ap);
900         return ret;
901 }
902
903 /**
904  List of Strings manipulation functions
905 **/
906
907 #define S_LIST_ABS 16 /* List Allocation Block Size */
908
909 /******************************************************************************
910  version of standard_sub_basic() for string lists; uses talloc_sub_basic()
911  for the work
912  *****************************************************************************/
913
914 bool str_list_sub_basic( char **list, const char *smb_name,
915                          const char *domain_name )
916 {
917         TALLOC_CTX *ctx = list;
918         char *s, *tmpstr;
919
920         while ( *list ) {
921                 s = *list;
922                 tmpstr = talloc_sub_basic(ctx, smb_name, domain_name, s);
923                 if ( !tmpstr ) {
924                         DEBUG(0,("str_list_sub_basic: "
925                                 "alloc_sub_basic() return NULL!\n"));
926                         return false;
927                 }
928
929                 TALLOC_FREE(*list);
930                 *list = tmpstr;
931
932                 list++;
933         }
934
935         return true;
936 }
937
938 /******************************************************************************
939  substitute a specific pattern in a string list
940  *****************************************************************************/
941
942 bool str_list_substitute(char **list, const char *pattern, const char *insert)
943 {
944         TALLOC_CTX *ctx = list;
945         char *p, *s, *t;
946         ssize_t ls, lp, li, ld, i, d;
947
948         if (!list)
949                 return false;
950         if (!pattern)
951                 return false;
952         if (!insert)
953                 return false;
954
955         lp = (ssize_t)strlen(pattern);
956         li = (ssize_t)strlen(insert);
957         ld = li -lp;
958
959         while (*list) {
960                 s = *list;
961                 ls = (ssize_t)strlen(s);
962
963                 while ((p = strstr_m(s, pattern))) {
964                         t = *list;
965                         d = p -t;
966                         if (ld) {
967                                 t = TALLOC_ARRAY(ctx, char, ls +ld +1);
968                                 if (!t) {
969                                         DEBUG(0,("str_list_substitute: "
970                                                 "Unable to allocate memory"));
971                                         return false;
972                                 }
973                                 memcpy(t, *list, d);
974                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
975                                 TALLOC_FREE(*list);
976                                 *list = t;
977                                 ls += ld;
978                                 s = t +d +li;
979                         }
980
981                         for (i = 0; i < li; i++) {
982                                 switch (insert[i]) {
983                                         case '`':
984                                         case '"':
985                                         case '\'':
986                                         case ';':
987                                         case '$':
988                                         case '%':
989                                         case '\r':
990                                         case '\n':
991                                                 t[d +i] = '_';
992                                                 break;
993                                         default:
994                                                 t[d +i] = insert[i];
995                                 }
996                         }
997                 }
998
999                 list++;
1000         }
1001
1002         return true;
1003 }
1004
1005
1006 #define IPSTR_LIST_SEP  ","
1007 #define IPSTR_LIST_CHAR ','
1008
1009 /**
1010  * Add ip string representation to ipstr list. Used also
1011  * as part of @function ipstr_list_make
1012  *
1013  * @param ipstr_list pointer to string containing ip list;
1014  *        MUST BE already allocated and IS reallocated if necessary
1015  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1016  *        as a result of reallocation)
1017  * @param ip IP address which is to be added to list
1018  * @return pointer to string appended with new ip and possibly
1019  *         reallocated to new length
1020  **/
1021
1022 static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service)
1023 {
1024         char *new_ipstr = NULL;
1025         char addr_buf[INET6_ADDRSTRLEN];
1026         int ret;
1027
1028         /* arguments checking */
1029         if (!ipstr_list || !service) {
1030                 return NULL;
1031         }
1032
1033         print_sockaddr(addr_buf,
1034                         sizeof(addr_buf),
1035                         &service->ss);
1036
1037         /* attempt to convert ip to a string and append colon separator to it */
1038         if (*ipstr_list) {
1039                 if (service->ss.ss_family == AF_INET) {
1040                         /* IPv4 */
1041                         ret = asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list,
1042                                        IPSTR_LIST_SEP, addr_buf,
1043                                        service->port);
1044                 } else {
1045                         /* IPv6 */
1046                         ret = asprintf(&new_ipstr, "%s%s[%s]:%d", *ipstr_list,
1047                                        IPSTR_LIST_SEP, addr_buf,
1048                                        service->port);
1049                 }
1050                 SAFE_FREE(*ipstr_list);
1051         } else {
1052                 if (service->ss.ss_family == AF_INET) {
1053                         /* IPv4 */
1054                         ret = asprintf(&new_ipstr, "%s:%d", addr_buf,
1055                                        service->port);
1056                 } else {
1057                         /* IPv6 */
1058                         ret = asprintf(&new_ipstr, "[%s]:%d", addr_buf,
1059                                        service->port);
1060                 }
1061         }
1062         if (ret == -1) {
1063                 return NULL;
1064         }
1065         *ipstr_list = new_ipstr;
1066         return *ipstr_list;
1067 }
1068
1069 /**
1070  * Allocate and initialise an ipstr list using ip adresses
1071  * passed as arguments.
1072  *
1073  * @param ipstr_list pointer to string meant to be allocated and set
1074  * @param ip_list array of ip addresses to place in the list
1075  * @param ip_count number of addresses stored in ip_list
1076  * @return pointer to allocated ip string
1077  **/
1078
1079 char *ipstr_list_make(char **ipstr_list,
1080                         const struct ip_service *ip_list,
1081                         int ip_count)
1082 {
1083         int i;
1084
1085         /* arguments checking */
1086         if (!ip_list || !ipstr_list) {
1087                 return 0;
1088         }
1089
1090         *ipstr_list = NULL;
1091
1092         /* process ip addresses given as arguments */
1093         for (i = 0; i < ip_count; i++) {
1094                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1095         }
1096
1097         return (*ipstr_list);
1098 }
1099
1100
1101 /**
1102  * Parse given ip string list into array of ip addresses
1103  * (as ip_service structures)
1104  *    e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
1105  *
1106  * @param ipstr ip string list to be parsed
1107  * @param ip_list pointer to array of ip addresses which is
1108  *        allocated by this function and must be freed by caller
1109  * @return number of successfully parsed addresses
1110  **/
1111
1112 int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list)
1113 {
1114         TALLOC_CTX *frame;
1115         char *token_str = NULL;
1116         size_t count;
1117         int i;
1118
1119         if (!ipstr_list || !ip_list)
1120                 return 0;
1121
1122         count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1123         if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
1124                 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n",
1125                                         (unsigned long)count));
1126                 return 0;
1127         }
1128
1129         frame = talloc_stackframe();
1130         for ( i=0; next_token_talloc(frame, &ipstr_list, &token_str,
1131                                 IPSTR_LIST_SEP) && i<count; i++ ) {
1132                 char *s = token_str;
1133                 char *p = strrchr(token_str, ':');
1134
1135                 if (p) {
1136                         *p = 0;
1137                         (*ip_list)[i].port = atoi(p+1);
1138                 }
1139
1140                 /* convert single token to ip address */
1141                 if (token_str[0] == '[') {
1142                         /* IPv6 address. */
1143                         s++;
1144                         p = strchr(token_str, ']');
1145                         if (!p) {
1146                                 continue;
1147                         }
1148                         *p = '\0';
1149                 }
1150                 if (!interpret_string_addr(&(*ip_list)[i].ss,
1151                                         s,
1152                                         AI_NUMERICHOST)) {
1153                         continue;
1154                 }
1155         }
1156         TALLOC_FREE(frame);
1157         return count;
1158 }
1159
1160 /**
1161  * Safely free ip string list
1162  *
1163  * @param ipstr_list ip string list to be freed
1164  **/
1165
1166 void ipstr_list_free(char* ipstr_list)
1167 {
1168         SAFE_FREE(ipstr_list);
1169 }
1170
1171 /* read a SMB_BIG_UINT from a string */
1172 uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1173 {
1174
1175         uint64_t val = (uint64_t)-1;
1176         const char *p = nptr;
1177
1178         if (!p) {
1179                 if (entptr) {
1180                         *entptr = p;
1181                 }
1182                 return val;
1183         }
1184
1185         while (*p && isspace(*p))
1186                 p++;
1187
1188         sscanf(p,"%"PRIu64,&val);
1189         if (entptr) {
1190                 while (*p && isdigit(*p))
1191                         p++;
1192                 *entptr = p;
1193         }
1194
1195         return val;
1196 }
1197
1198 /* Convert a size specification to a count of bytes. We accept the following
1199  * suffixes:
1200  *          bytes if there is no suffix
1201  *      kK  kibibytes
1202  *      mM  mebibytes
1203  *      gG  gibibytes
1204  *      tT  tibibytes
1205  *      pP  whatever the ISO name for petabytes is
1206  *
1207  *  Returns 0 if the string can't be converted.
1208  */
1209 SMB_OFF_T conv_str_size(const char * str)
1210 {
1211         SMB_OFF_T lval_orig;
1212         SMB_OFF_T lval;
1213         char * end;
1214
1215         if (str == NULL || *str == '\0') {
1216                 return 0;
1217         }
1218
1219 #ifdef HAVE_STRTOULL
1220         if (sizeof(SMB_OFF_T) == 8) {
1221                 lval = strtoull(str, &end, 10 /* base */);
1222         } else {
1223                 lval = strtoul(str, &end, 10 /* base */);
1224         }
1225 #else
1226         lval = strtoul(str, &end, 10 /* base */);
1227 #endif
1228
1229         if (end == NULL || end == str) {
1230                 return 0;
1231         }
1232
1233         if (*end == '\0') {
1234                 return lval;
1235         }
1236
1237         lval_orig = lval;
1238
1239         if (strwicmp(end, "K") == 0) {
1240                 lval *= (SMB_OFF_T)1024;
1241         } else if (strwicmp(end, "M") == 0) {
1242                 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
1243         } else if (strwicmp(end, "G") == 0) {
1244                 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
1245                          (SMB_OFF_T)1024);
1246         } else if (strwicmp(end, "T") == 0) {
1247                 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
1248                          (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
1249         } else if (strwicmp(end, "P") == 0) {
1250                 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
1251                          (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
1252                          (SMB_OFF_T)1024);
1253         } else {
1254                 return 0;
1255         }
1256
1257         /*
1258          * Primitive attempt to detect wrapping on platforms with
1259          * 4-byte SMB_OFF_T. It's better to let the caller handle a
1260          * failure than some random number.
1261          */
1262         if (lval_orig <= lval) {
1263                 return 0;
1264         }
1265
1266         return lval;
1267 }
1268
1269 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
1270  * error checking in between. The indiation that something weird happened is
1271  * string==NULL */
1272
1273 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
1274                     size_t *bufsize, const char *fmt, ...)
1275 {
1276         va_list ap;
1277         char *newstr;
1278         int ret;
1279         bool increased;
1280
1281         /* len<0 is an internal marker that something failed */
1282         if (*len < 0)
1283                 goto error;
1284
1285         if (*string == NULL) {
1286                 if (*bufsize == 0)
1287                         *bufsize = 128;
1288
1289                 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
1290                 if (*string == NULL)
1291                         goto error;
1292         }
1293
1294         va_start(ap, fmt);
1295         ret = vasprintf(&newstr, fmt, ap);
1296         va_end(ap);
1297
1298         if (ret < 0)
1299                 goto error;
1300
1301         increased = false;
1302
1303         while ((*len)+ret >= *bufsize) {
1304                 increased = true;
1305                 *bufsize *= 2;
1306                 if (*bufsize >= (1024*1024*256))
1307                         goto error;
1308         }
1309
1310         if (increased) {
1311                 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
1312                                                *bufsize);
1313                 if (*string == NULL) {
1314                         goto error;
1315                 }
1316         }
1317
1318         StrnCpy((*string)+(*len), newstr, ret);
1319         (*len) += ret;
1320         free(newstr);
1321         return;
1322
1323  error:
1324         *len = -1;
1325         *string = NULL;
1326 }
1327
1328 /*
1329  * asprintf into a string and strupper_m it after that.
1330  */
1331
1332 int asprintf_strupper_m(char **strp, const char *fmt, ...)
1333 {
1334         va_list ap;
1335         char *result;
1336         int ret;
1337
1338         va_start(ap, fmt);
1339         ret = vasprintf(&result, fmt, ap);
1340         va_end(ap);
1341
1342         if (ret == -1)
1343                 return -1;
1344
1345         strupper_m(result);
1346         *strp = result;
1347         return ret;
1348 }
1349
1350 char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
1351 {
1352         va_list ap;
1353         char *ret;
1354
1355         va_start(ap, fmt);
1356         ret = talloc_vasprintf(t, fmt, ap);
1357         va_end(ap);
1358
1359         if (ret == NULL) {
1360                 return NULL;
1361         }
1362         strupper_m(ret);
1363         return ret;
1364 }
1365
1366 char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
1367 {
1368         va_list ap;
1369         char *ret;
1370
1371         va_start(ap, fmt);
1372         ret = talloc_vasprintf(t, fmt, ap);
1373         va_end(ap);
1374
1375         if (ret == NULL) {
1376                 return NULL;
1377         }
1378         strlower_m(ret);
1379         return ret;
1380 }
1381
1382
1383 /*
1384    Returns the substring from src between the first occurrence of
1385    the char "front" and the first occurence of the char "back".
1386    Mallocs the return string which must be freed.  Not for use
1387    with wide character strings.
1388 */
1389 char *sstring_sub(const char *src, char front, char back)
1390 {
1391         char *temp1, *temp2, *temp3;
1392         ptrdiff_t len;
1393
1394         temp1 = strchr(src, front);
1395         if (temp1 == NULL) return NULL;
1396         temp2 = strchr(src, back);
1397         if (temp2 == NULL) return NULL;
1398         len = temp2 - temp1;
1399         if (len <= 0) return NULL;
1400         temp3 = (char*)SMB_MALLOC(len);
1401         if (temp3 == NULL) {
1402                 DEBUG(1,("Malloc failure in sstring_sub\n"));
1403                 return NULL;
1404         }
1405         memcpy(temp3, temp1+1, len-1);
1406         temp3[len-1] = '\0';
1407         return temp3;
1408 }
1409
1410 /********************************************************************
1411  Check a string for any occurrences of a specified list of invalid
1412  characters.
1413 ********************************************************************/
1414
1415 bool validate_net_name( const char *name,
1416                 const char *invalid_chars,
1417                 int max_len)
1418 {
1419         int i;
1420
1421         if (!name) {
1422                 return false;
1423         }
1424
1425         for ( i=0; i<max_len && name[i]; i++ ) {
1426                 /* fail if strchr_m() finds one of the invalid characters */
1427                 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
1428                         return false;
1429                 }
1430         }
1431
1432         return true;
1433 }
1434
1435
1436 /*******************************************************************
1437  Add a shell escape character '\' to any character not in a known list
1438  of characters. UNIX charset format.
1439 *******************************************************************/
1440
1441 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
1442 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
1443
1444 char *escape_shell_string(const char *src)
1445 {
1446         size_t srclen = strlen(src);
1447         char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
1448         char *dest = ret;
1449         bool in_s_quote = false;
1450         bool in_d_quote = false;
1451         bool next_escaped = false;
1452
1453         if (!ret) {
1454                 return NULL;
1455         }
1456
1457         while (*src) {
1458                 size_t c_size;
1459                 codepoint_t c = next_codepoint(src, &c_size);
1460
1461                 if (c == INVALID_CODEPOINT) {
1462                         SAFE_FREE(ret);
1463                         return NULL;
1464                 }
1465
1466                 if (c_size > 1) {
1467                         memcpy(dest, src, c_size);
1468                         src += c_size;
1469                         dest += c_size;
1470                         next_escaped = false;
1471                         continue;
1472                 }
1473
1474                 /*
1475                  * Deal with backslash escaped state.
1476                  * This only lasts for one character.
1477                  */
1478
1479                 if (next_escaped) {
1480                         *dest++ = *src++;
1481                         next_escaped = false;
1482                         continue;
1483                 }
1484
1485                 /*
1486                  * Deal with single quote state. The
1487                  * only thing we care about is exiting
1488                  * this state.
1489                  */
1490
1491                 if (in_s_quote) {
1492                         if (*src == '\'') {
1493                                 in_s_quote = false;
1494                         }
1495                         *dest++ = *src++;
1496                         continue;
1497                 }
1498
1499                 /*
1500                  * Deal with double quote state. The most
1501                  * complex state. We must cope with \, meaning
1502                  * possibly escape next char (depending what it
1503                  * is), ", meaning exit this state, and possibly
1504                  * add an \ escape to any unprotected character
1505                  * (listed in INSIDE_DQUOTE_LIST).
1506                  */
1507
1508                 if (in_d_quote) {
1509                         if (*src == '\\') {
1510                                 /*
1511                                  * Next character might be escaped.
1512                                  * We have to peek. Inside double
1513                                  * quotes only INSIDE_DQUOTE_LIST
1514                                  * characters are escaped by a \.
1515                                  */
1516
1517                                 char nextchar;
1518
1519                                 c = next_codepoint(&src[1], &c_size);
1520                                 if (c == INVALID_CODEPOINT) {
1521                                         SAFE_FREE(ret);
1522                                         return NULL;
1523                                 }
1524                                 if (c_size > 1) {
1525                                         /*
1526                                          * Don't escape the next char.
1527                                          * Just copy the \.
1528                                          */
1529                                         *dest++ = *src++;
1530                                         continue;
1531                                 }
1532
1533                                 nextchar = src[1];
1534
1535                                 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
1536                                                         (int)nextchar)) {
1537                                         next_escaped = true;
1538                                 }
1539                                 *dest++ = *src++;
1540                                 continue;
1541                         }
1542
1543                         if (*src == '\"') {
1544                                 /* Exit double quote state. */
1545                                 in_d_quote = false;
1546                                 *dest++ = *src++;
1547                                 continue;
1548                         }
1549
1550                         /*
1551                          * We know the character isn't \ or ",
1552                          * so escape it if it's any of the other
1553                          * possible unprotected characters.
1554                          */
1555
1556                         if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
1557                                 *dest++ = '\\';
1558                         }
1559                         *dest++ = *src++;
1560                         continue;
1561                 }
1562
1563                 /*
1564                  * From here to the end of the loop we're
1565                  * not in the single or double quote state.
1566                  */
1567
1568                 if (*src == '\\') {
1569                         /* Next character must be escaped. */
1570                         next_escaped = true;
1571                         *dest++ = *src++;
1572                         continue;
1573                 }
1574
1575                 if (*src == '\'') {
1576                         /* Go into single quote state. */
1577                         in_s_quote = true;
1578                         *dest++ = *src++;
1579                         continue;
1580                 }
1581
1582                 if (*src == '\"') {
1583                         /* Go into double quote state. */
1584                         in_d_quote = true;
1585                         *dest++ = *src++;
1586                         continue;
1587                 }
1588
1589                 /* Check if we need to escape the character. */
1590
1591                 if (!strchr(INCLUDE_LIST, (int)*src)) {
1592                         *dest++ = '\\';
1593                 }
1594                 *dest++ = *src++;
1595         }
1596         *dest++ = '\0';
1597         return ret;
1598 }
1599
1600 /***************************************************
1601  str_list_make, v3 version. The v4 version does not
1602  look at quoted strings with embedded blanks, so
1603  do NOT merge this function please!
1604 ***************************************************/
1605
1606 #define S_LIST_ABS 16 /* List Allocation Block Size */
1607
1608 char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
1609         const char *sep)
1610 {
1611         char **list;
1612         const char *str;
1613         char *s, *tok;
1614         int num, lsize;
1615
1616         if (!string || !*string)
1617                 return NULL;
1618
1619         list = TALLOC_ARRAY(mem_ctx, char *, S_LIST_ABS+1);
1620         if (list == NULL) {
1621                 return NULL;
1622         }
1623         lsize = S_LIST_ABS;
1624
1625         s = talloc_strdup(list, string);
1626         if (s == NULL) {
1627                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1628                 TALLOC_FREE(list);
1629                 return NULL;
1630         }
1631         if (!sep) sep = LIST_SEP;
1632
1633         num = 0;
1634         str = s;
1635
1636         while (next_token_talloc(list, &str, &tok, sep)) {
1637
1638                 if (num == lsize) {
1639                         char **tmp;
1640
1641                         lsize += S_LIST_ABS;
1642
1643                         tmp = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *,
1644                                                    lsize + 1);
1645                         if (tmp == NULL) {
1646                                 DEBUG(0,("str_list_make: "
1647                                         "Unable to allocate memory"));
1648                                 TALLOC_FREE(list);
1649                                 return NULL;
1650                         }
1651
1652                         list = tmp;
1653
1654                         memset (&list[num], 0,
1655                                 ((sizeof(char**)) * (S_LIST_ABS +1)));
1656                 }
1657
1658                 list[num] = tok;
1659                 num += 1;
1660         }
1661
1662         list[num] = NULL;
1663
1664         TALLOC_FREE(s);
1665         return list;
1666 }
1667
1668 char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
1669 {
1670         fstring tmp;
1671
1672         alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
1673         return talloc_strdup(mem_ctx, tmp);
1674 }