4d76cc0a9f5e1d36426295390c3d9c8ad89fa568
[ira/wip.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 #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
800
801 /**
802  Convert a string to lower case.
803 **/
804 _PUBLIC_ void strlower_m(char *s)
805 {
806         char *d;
807         struct smb_iconv_handle *iconv_handle;
808
809         iconv_handle = get_iconv_handle();
810
811         d = s;
812
813         while (*s) {
814                 size_t c_size, c_size2;
815                 codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
816                 c_size2 = push_codepoint_handle(iconv_handle, d, tolower_m(c));
817                 if (c_size2 > c_size) {
818                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
819                                  c, tolower_m(c), (int)c_size, (int)c_size2));
820                         smb_panic("codepoint expansion in strlower_m\n");
821                 }
822                 s += c_size;
823                 d += c_size2;
824         }
825         *d = 0;
826 }
827
828 #endif
829
830 /**
831  Convert a string to lower case.
832 **/
833
834 void strlower_m(char *s)
835 {
836         size_t len;
837         int errno_save;
838
839         /* this is quite a common operation, so we want it to be
840            fast. We optimise for the ascii case, knowing that all our
841            supported multi-byte character sets are ascii-compatible
842            (ie. they match for the first 128 chars) */
843
844         while (*s && !(((unsigned char)s[0]) & 0x80)) {
845                 *s = tolower_ascii((unsigned char)*s);
846                 s++;
847         }
848
849         if (!*s)
850                 return;
851
852         /* I assume that lowercased string takes the same number of bytes
853          * as source string even in UTF-8 encoding. (VIV) */
854         len = strlen(s) + 1;
855         errno_save = errno;
856         errno = 0;
857         unix_strlower(s,len,s,len);
858         /* Catch mb conversion errors that may not terminate. */
859         if (errno)
860                 s[len-1] = '\0';
861         errno = errno_save;
862 }
863
864 static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
865 {
866         size_t size;
867         smb_ucs2_t *buffer;
868         bool ret;
869
870         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
871                 return (size_t)-1;
872         }
873
874         if (!strupper_w(buffer) && (dest == src)) {
875                 TALLOC_FREE(buffer);
876                 return srclen;
877         }
878
879         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
880         TALLOC_FREE(buffer);
881         return ret;
882 }
883
884 #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
885
886 /**
887  Convert a string to UPPER case.
888 **/
889 _PUBLIC_ void strupper_m(char *s)
890 {
891         char *d;
892         struct smb_iconv_handle *iconv_handle;
893
894         iconv_handle = get_iconv_handle();
895
896         d = s;
897
898         while (*s) {
899                 size_t c_size, c_size2;
900                 codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
901                 c_size2 = push_codepoint_handle(iconv_handle, d, toupper_m(c));
902                 if (c_size2 > c_size) {
903                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
904                                  c, toupper_m(c), (int)c_size, (int)c_size2));
905                         smb_panic("codepoint expansion in strupper_m\n");
906                 }
907                 s += c_size;
908                 d += c_size2;
909         }
910         *d = 0;
911 }
912
913 #endif
914
915 /**
916  Convert a string to upper case.
917 **/
918
919 void strupper_m(char *s)
920 {
921         size_t len;
922         int errno_save;
923
924         /* this is quite a common operation, so we want it to be
925            fast. We optimise for the ascii case, knowing that all our
926            supported multi-byte character sets are ascii-compatible
927            (ie. they match for the first 128 chars) */
928
929         while (*s && !(((unsigned char)s[0]) & 0x80)) {
930                 *s = toupper_ascii_fast((unsigned char)*s);
931                 s++;
932         }
933
934         if (!*s)
935                 return;
936
937         /* I assume that lowercased string takes the same number of bytes
938          * as source string even in multibyte encoding. (VIV) */
939         len = strlen(s) + 1;
940         errno_save = errno;
941         errno = 0;
942         unix_strupper(s,len,s,len);
943         /* Catch mb conversion errors that may not terminate. */
944         if (errno)
945                 s[len-1] = '\0';
946         errno = errno_save;
947 }
948
949 /**
950  Just a typesafety wrapper for snprintf into a fstring.
951 **/
952
953 int fstr_sprintf(fstring s, const char *fmt, ...)
954 {
955         va_list ap;
956         int ret;
957
958         va_start(ap, fmt);
959         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
960         va_end(ap);
961         return ret;
962 }
963
964 /**
965  List of Strings manipulation functions
966 **/
967
968 #define S_LIST_ABS 16 /* List Allocation Block Size */
969
970 /******************************************************************************
971  version of standard_sub_basic() for string lists; uses talloc_sub_basic()
972  for the work
973  *****************************************************************************/
974
975 bool str_list_sub_basic( char **list, const char *smb_name,
976                          const char *domain_name )
977 {
978         TALLOC_CTX *ctx = list;
979         char *s, *tmpstr;
980
981         while ( *list ) {
982                 s = *list;
983                 tmpstr = talloc_sub_basic(ctx, smb_name, domain_name, s);
984                 if ( !tmpstr ) {
985                         DEBUG(0,("str_list_sub_basic: "
986                                 "alloc_sub_basic() return NULL!\n"));
987                         return false;
988                 }
989
990                 TALLOC_FREE(*list);
991                 *list = tmpstr;
992
993                 list++;
994         }
995
996         return true;
997 }
998
999 /******************************************************************************
1000  substitute a specific pattern in a string list
1001  *****************************************************************************/
1002
1003 bool str_list_substitute(char **list, const char *pattern, const char *insert)
1004 {
1005         TALLOC_CTX *ctx = list;
1006         char *p, *s, *t;
1007         ssize_t ls, lp, li, ld, i, d;
1008
1009         if (!list)
1010                 return false;
1011         if (!pattern)
1012                 return false;
1013         if (!insert)
1014                 return false;
1015
1016         lp = (ssize_t)strlen(pattern);
1017         li = (ssize_t)strlen(insert);
1018         ld = li -lp;
1019
1020         while (*list) {
1021                 s = *list;
1022                 ls = (ssize_t)strlen(s);
1023
1024                 while ((p = strstr_m(s, pattern))) {
1025                         t = *list;
1026                         d = p -t;
1027                         if (ld) {
1028                                 t = TALLOC_ARRAY(ctx, char, ls +ld +1);
1029                                 if (!t) {
1030                                         DEBUG(0,("str_list_substitute: "
1031                                                 "Unable to allocate memory"));
1032                                         return false;
1033                                 }
1034                                 memcpy(t, *list, d);
1035                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1036                                 TALLOC_FREE(*list);
1037                                 *list = t;
1038                                 ls += ld;
1039                                 s = t +d +li;
1040                         }
1041
1042                         for (i = 0; i < li; i++) {
1043                                 switch (insert[i]) {
1044                                         case '`':
1045                                         case '"':
1046                                         case '\'':
1047                                         case ';':
1048                                         case '$':
1049                                         case '%':
1050                                         case '\r':
1051                                         case '\n':
1052                                                 t[d +i] = '_';
1053                                                 break;
1054                                         default:
1055                                                 t[d +i] = insert[i];
1056                                 }
1057                         }
1058                 }
1059
1060                 list++;
1061         }
1062
1063         return true;
1064 }
1065
1066
1067 #define IPSTR_LIST_SEP  ","
1068 #define IPSTR_LIST_CHAR ','
1069
1070 /**
1071  * Add ip string representation to ipstr list. Used also
1072  * as part of @function ipstr_list_make
1073  *
1074  * @param ipstr_list pointer to string containing ip list;
1075  *        MUST BE already allocated and IS reallocated if necessary
1076  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1077  *        as a result of reallocation)
1078  * @param ip IP address which is to be added to list
1079  * @return pointer to string appended with new ip and possibly
1080  *         reallocated to new length
1081  **/
1082
1083 static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service)
1084 {
1085         char *new_ipstr = NULL;
1086         char addr_buf[INET6_ADDRSTRLEN];
1087         int ret;
1088
1089         /* arguments checking */
1090         if (!ipstr_list || !service) {
1091                 return NULL;
1092         }
1093
1094         print_sockaddr(addr_buf,
1095                         sizeof(addr_buf),
1096                         &service->ss);
1097
1098         /* attempt to convert ip to a string and append colon separator to it */
1099         if (*ipstr_list) {
1100                 if (service->ss.ss_family == AF_INET) {
1101                         /* IPv4 */
1102                         ret = asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list,
1103                                        IPSTR_LIST_SEP, addr_buf,
1104                                        service->port);
1105                 } else {
1106                         /* IPv6 */
1107                         ret = asprintf(&new_ipstr, "%s%s[%s]:%d", *ipstr_list,
1108                                        IPSTR_LIST_SEP, addr_buf,
1109                                        service->port);
1110                 }
1111                 SAFE_FREE(*ipstr_list);
1112         } else {
1113                 if (service->ss.ss_family == AF_INET) {
1114                         /* IPv4 */
1115                         ret = asprintf(&new_ipstr, "%s:%d", addr_buf,
1116                                        service->port);
1117                 } else {
1118                         /* IPv6 */
1119                         ret = asprintf(&new_ipstr, "[%s]:%d", addr_buf,
1120                                        service->port);
1121                 }
1122         }
1123         if (ret == -1) {
1124                 return NULL;
1125         }
1126         *ipstr_list = new_ipstr;
1127         return *ipstr_list;
1128 }
1129
1130 /**
1131  * Allocate and initialise an ipstr list using ip adresses
1132  * passed as arguments.
1133  *
1134  * @param ipstr_list pointer to string meant to be allocated and set
1135  * @param ip_list array of ip addresses to place in the list
1136  * @param ip_count number of addresses stored in ip_list
1137  * @return pointer to allocated ip string
1138  **/
1139
1140 char *ipstr_list_make(char **ipstr_list,
1141                         const struct ip_service *ip_list,
1142                         int ip_count)
1143 {
1144         int i;
1145
1146         /* arguments checking */
1147         if (!ip_list || !ipstr_list) {
1148                 return 0;
1149         }
1150
1151         *ipstr_list = NULL;
1152
1153         /* process ip addresses given as arguments */
1154         for (i = 0; i < ip_count; i++) {
1155                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1156         }
1157
1158         return (*ipstr_list);
1159 }
1160
1161
1162 /**
1163  * Parse given ip string list into array of ip addresses
1164  * (as ip_service structures)
1165  *    e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
1166  *
1167  * @param ipstr ip string list to be parsed
1168  * @param ip_list pointer to array of ip addresses which is
1169  *        allocated by this function and must be freed by caller
1170  * @return number of successfully parsed addresses
1171  **/
1172
1173 int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list)
1174 {
1175         TALLOC_CTX *frame;
1176         char *token_str = NULL;
1177         size_t count;
1178         int i;
1179
1180         if (!ipstr_list || !ip_list)
1181                 return 0;
1182
1183         count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1184         if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
1185                 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n",
1186                                         (unsigned long)count));
1187                 return 0;
1188         }
1189
1190         frame = talloc_stackframe();
1191         for ( i=0; next_token_talloc(frame, &ipstr_list, &token_str,
1192                                 IPSTR_LIST_SEP) && i<count; i++ ) {
1193                 char *s = token_str;
1194                 char *p = strrchr(token_str, ':');
1195
1196                 if (p) {
1197                         *p = 0;
1198                         (*ip_list)[i].port = atoi(p+1);
1199                 }
1200
1201                 /* convert single token to ip address */
1202                 if (token_str[0] == '[') {
1203                         /* IPv6 address. */
1204                         s++;
1205                         p = strchr(token_str, ']');
1206                         if (!p) {
1207                                 continue;
1208                         }
1209                         *p = '\0';
1210                 }
1211                 if (!interpret_string_addr(&(*ip_list)[i].ss,
1212                                         s,
1213                                         AI_NUMERICHOST)) {
1214                         continue;
1215                 }
1216         }
1217         TALLOC_FREE(frame);
1218         return count;
1219 }
1220
1221 /**
1222  * Safely free ip string list
1223  *
1224  * @param ipstr_list ip string list to be freed
1225  **/
1226
1227 void ipstr_list_free(char* ipstr_list)
1228 {
1229         SAFE_FREE(ipstr_list);
1230 }
1231
1232 /* read a SMB_BIG_UINT from a string */
1233 uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1234 {
1235
1236         uint64_t val = (uint64_t)-1;
1237         const char *p = nptr;
1238
1239         if (!p) {
1240                 if (entptr) {
1241                         *entptr = p;
1242                 }
1243                 return val;
1244         }
1245
1246         while (*p && isspace(*p))
1247                 p++;
1248
1249         sscanf(p,"%"PRIu64,&val);
1250         if (entptr) {
1251                 while (*p && isdigit(*p))
1252                         p++;
1253                 *entptr = p;
1254         }
1255
1256         return val;
1257 }
1258
1259 /* Convert a size specification to a count of bytes. We accept the following
1260  * suffixes:
1261  *          bytes if there is no suffix
1262  *      kK  kibibytes
1263  *      mM  mebibytes
1264  *      gG  gibibytes
1265  *      tT  tibibytes
1266  *      pP  whatever the ISO name for petabytes is
1267  *
1268  *  Returns 0 if the string can't be converted.
1269  */
1270 uint64_t conv_str_size(const char * str)
1271 {
1272         uint64_t lval_orig;
1273         uint64_t lval;
1274         char * end;
1275
1276         if (str == NULL || *str == '\0') {
1277                 return 0;
1278         }
1279
1280         lval = strtoull(str, &end, 10 /* base */);
1281
1282         if (end == NULL || end == str) {
1283                 return 0;
1284         }
1285
1286         if (*end == '\0') {
1287                 return lval;
1288         }
1289
1290         lval_orig = lval;
1291
1292         if (strwicmp(end, "K") == 0) {
1293                 lval *= 1024ULL;
1294         } else if (strwicmp(end, "M") == 0) {
1295                 lval *= (1024ULL * 1024ULL);
1296         } else if (strwicmp(end, "G") == 0) {
1297                 lval *= (1024ULL * 1024ULL *
1298                          1024ULL);
1299         } else if (strwicmp(end, "T") == 0) {
1300                 lval *= (1024ULL * 1024ULL *
1301                          1024ULL * 1024ULL);
1302         } else if (strwicmp(end, "P") == 0) {
1303                 lval *= (1024ULL * 1024ULL *
1304                          1024ULL * 1024ULL *
1305                          1024ULL);
1306         } else {
1307                 return 0;
1308         }
1309
1310         return lval;
1311 }
1312
1313 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
1314  * error checking in between. The indiation that something weird happened is
1315  * string==NULL */
1316
1317 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
1318                     size_t *bufsize, const char *fmt, ...)
1319 {
1320         va_list ap;
1321         char *newstr;
1322         int ret;
1323         bool increased;
1324
1325         /* len<0 is an internal marker that something failed */
1326         if (*len < 0)
1327                 goto error;
1328
1329         if (*string == NULL) {
1330                 if (*bufsize == 0)
1331                         *bufsize = 128;
1332
1333                 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
1334                 if (*string == NULL)
1335                         goto error;
1336         }
1337
1338         va_start(ap, fmt);
1339         ret = vasprintf(&newstr, fmt, ap);
1340         va_end(ap);
1341
1342         if (ret < 0)
1343                 goto error;
1344
1345         increased = false;
1346
1347         while ((*len)+ret >= *bufsize) {
1348                 increased = true;
1349                 *bufsize *= 2;
1350                 if (*bufsize >= (1024*1024*256))
1351                         goto error;
1352         }
1353
1354         if (increased) {
1355                 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
1356                                                *bufsize);
1357                 if (*string == NULL) {
1358                         goto error;
1359                 }
1360         }
1361
1362         StrnCpy((*string)+(*len), newstr, ret);
1363         (*len) += ret;
1364         free(newstr);
1365         return;
1366
1367  error:
1368         *len = -1;
1369         *string = NULL;
1370 }
1371
1372 /*
1373  * asprintf into a string and strupper_m it after that.
1374  */
1375
1376 int asprintf_strupper_m(char **strp, const char *fmt, ...)
1377 {
1378         va_list ap;
1379         char *result;
1380         int ret;
1381
1382         va_start(ap, fmt);
1383         ret = vasprintf(&result, fmt, ap);
1384         va_end(ap);
1385
1386         if (ret == -1)
1387                 return -1;
1388
1389         strupper_m(result);
1390         *strp = result;
1391         return ret;
1392 }
1393
1394 char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
1395 {
1396         va_list ap;
1397         char *ret;
1398
1399         va_start(ap, fmt);
1400         ret = talloc_vasprintf(t, fmt, ap);
1401         va_end(ap);
1402
1403         if (ret == NULL) {
1404                 return NULL;
1405         }
1406         strupper_m(ret);
1407         return ret;
1408 }
1409
1410 char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
1411 {
1412         va_list ap;
1413         char *ret;
1414
1415         va_start(ap, fmt);
1416         ret = talloc_vasprintf(t, fmt, ap);
1417         va_end(ap);
1418
1419         if (ret == NULL) {
1420                 return NULL;
1421         }
1422         strlower_m(ret);
1423         return ret;
1424 }
1425
1426
1427 /*
1428    Returns the substring from src between the first occurrence of
1429    the char "front" and the first occurence of the char "back".
1430    Mallocs the return string which must be freed.  Not for use
1431    with wide character strings.
1432 */
1433 char *sstring_sub(const char *src, char front, char back)
1434 {
1435         char *temp1, *temp2, *temp3;
1436         ptrdiff_t len;
1437
1438         temp1 = strchr(src, front);
1439         if (temp1 == NULL) return NULL;
1440         temp2 = strchr(src, back);
1441         if (temp2 == NULL) return NULL;
1442         len = temp2 - temp1;
1443         if (len <= 0) return NULL;
1444         temp3 = (char*)SMB_MALLOC(len);
1445         if (temp3 == NULL) {
1446                 DEBUG(1,("Malloc failure in sstring_sub\n"));
1447                 return NULL;
1448         }
1449         memcpy(temp3, temp1+1, len-1);
1450         temp3[len-1] = '\0';
1451         return temp3;
1452 }
1453
1454 /********************************************************************
1455  Check a string for any occurrences of a specified list of invalid
1456  characters.
1457 ********************************************************************/
1458
1459 bool validate_net_name( const char *name,
1460                 const char *invalid_chars,
1461                 int max_len)
1462 {
1463         int i;
1464
1465         if (!name) {
1466                 return false;
1467         }
1468
1469         for ( i=0; i<max_len && name[i]; i++ ) {
1470                 /* fail if strchr_m() finds one of the invalid characters */
1471                 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
1472                         return false;
1473                 }
1474         }
1475
1476         return true;
1477 }
1478
1479
1480 /*******************************************************************
1481  Add a shell escape character '\' to any character not in a known list
1482  of characters. UNIX charset format.
1483 *******************************************************************/
1484
1485 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
1486 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
1487
1488 char *escape_shell_string(const char *src)
1489 {
1490         size_t srclen = strlen(src);
1491         char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
1492         char *dest = ret;
1493         bool in_s_quote = false;
1494         bool in_d_quote = false;
1495         bool next_escaped = false;
1496
1497         if (!ret) {
1498                 return NULL;
1499         }
1500
1501         while (*src) {
1502                 size_t c_size;
1503                 codepoint_t c = next_codepoint(src, &c_size);
1504
1505                 if (c == INVALID_CODEPOINT) {
1506                         SAFE_FREE(ret);
1507                         return NULL;
1508                 }
1509
1510                 if (c_size > 1) {
1511                         memcpy(dest, src, c_size);
1512                         src += c_size;
1513                         dest += c_size;
1514                         next_escaped = false;
1515                         continue;
1516                 }
1517
1518                 /*
1519                  * Deal with backslash escaped state.
1520                  * This only lasts for one character.
1521                  */
1522
1523                 if (next_escaped) {
1524                         *dest++ = *src++;
1525                         next_escaped = false;
1526                         continue;
1527                 }
1528
1529                 /*
1530                  * Deal with single quote state. The
1531                  * only thing we care about is exiting
1532                  * this state.
1533                  */
1534
1535                 if (in_s_quote) {
1536                         if (*src == '\'') {
1537                                 in_s_quote = false;
1538                         }
1539                         *dest++ = *src++;
1540                         continue;
1541                 }
1542
1543                 /*
1544                  * Deal with double quote state. The most
1545                  * complex state. We must cope with \, meaning
1546                  * possibly escape next char (depending what it
1547                  * is), ", meaning exit this state, and possibly
1548                  * add an \ escape to any unprotected character
1549                  * (listed in INSIDE_DQUOTE_LIST).
1550                  */
1551
1552                 if (in_d_quote) {
1553                         if (*src == '\\') {
1554                                 /*
1555                                  * Next character might be escaped.
1556                                  * We have to peek. Inside double
1557                                  * quotes only INSIDE_DQUOTE_LIST
1558                                  * characters are escaped by a \.
1559                                  */
1560
1561                                 char nextchar;
1562
1563                                 c = next_codepoint(&src[1], &c_size);
1564                                 if (c == INVALID_CODEPOINT) {
1565                                         SAFE_FREE(ret);
1566                                         return NULL;
1567                                 }
1568                                 if (c_size > 1) {
1569                                         /*
1570                                          * Don't escape the next char.
1571                                          * Just copy the \.
1572                                          */
1573                                         *dest++ = *src++;
1574                                         continue;
1575                                 }
1576
1577                                 nextchar = src[1];
1578
1579                                 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
1580                                                         (int)nextchar)) {
1581                                         next_escaped = true;
1582                                 }
1583                                 *dest++ = *src++;
1584                                 continue;
1585                         }
1586
1587                         if (*src == '\"') {
1588                                 /* Exit double quote state. */
1589                                 in_d_quote = false;
1590                                 *dest++ = *src++;
1591                                 continue;
1592                         }
1593
1594                         /*
1595                          * We know the character isn't \ or ",
1596                          * so escape it if it's any of the other
1597                          * possible unprotected characters.
1598                          */
1599
1600                         if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
1601                                 *dest++ = '\\';
1602                         }
1603                         *dest++ = *src++;
1604                         continue;
1605                 }
1606
1607                 /*
1608                  * From here to the end of the loop we're
1609                  * not in the single or double quote state.
1610                  */
1611
1612                 if (*src == '\\') {
1613                         /* Next character must be escaped. */
1614                         next_escaped = true;
1615                         *dest++ = *src++;
1616                         continue;
1617                 }
1618
1619                 if (*src == '\'') {
1620                         /* Go into single quote state. */
1621                         in_s_quote = true;
1622                         *dest++ = *src++;
1623                         continue;
1624                 }
1625
1626                 if (*src == '\"') {
1627                         /* Go into double quote state. */
1628                         in_d_quote = true;
1629                         *dest++ = *src++;
1630                         continue;
1631                 }
1632
1633                 /* Check if we need to escape the character. */
1634
1635                 if (!strchr(INCLUDE_LIST, (int)*src)) {
1636                         *dest++ = '\\';
1637                 }
1638                 *dest++ = *src++;
1639         }
1640         *dest++ = '\0';
1641         return ret;
1642 }
1643
1644 /***************************************************
1645  str_list_make, v3 version. The v4 version does not
1646  look at quoted strings with embedded blanks, so
1647  do NOT merge this function please!
1648 ***************************************************/
1649
1650 #define S_LIST_ABS 16 /* List Allocation Block Size */
1651
1652 char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
1653         const char *sep)
1654 {
1655         char **list;
1656         const char *str;
1657         char *s, *tok;
1658         int num, lsize;
1659
1660         if (!string || !*string)
1661                 return NULL;
1662
1663         list = TALLOC_ARRAY(mem_ctx, char *, S_LIST_ABS+1);
1664         if (list == NULL) {
1665                 return NULL;
1666         }
1667         lsize = S_LIST_ABS;
1668
1669         s = talloc_strdup(list, string);
1670         if (s == NULL) {
1671                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1672                 TALLOC_FREE(list);
1673                 return NULL;
1674         }
1675         if (!sep) sep = LIST_SEP;
1676
1677         num = 0;
1678         str = s;
1679
1680         while (next_token_talloc(list, &str, &tok, sep)) {
1681
1682                 if (num == lsize) {
1683                         char **tmp;
1684
1685                         lsize += S_LIST_ABS;
1686
1687                         tmp = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *,
1688                                                    lsize + 1);
1689                         if (tmp == NULL) {
1690                                 DEBUG(0,("str_list_make: "
1691                                         "Unable to allocate memory"));
1692                                 TALLOC_FREE(list);
1693                                 return NULL;
1694                         }
1695
1696                         list = tmp;
1697
1698                         memset (&list[num], 0,
1699                                 ((sizeof(char**)) * (S_LIST_ABS +1)));
1700                 }
1701
1702                 list[num] = tok;
1703                 num += 1;
1704         }
1705
1706         list[num] = NULL;
1707
1708         TALLOC_FREE(s);
1709         return list;
1710 }
1711
1712 char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
1713 {
1714         fstring tmp;
1715
1716         alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
1717         return talloc_strdup(mem_ctx, tmp);
1718 }