include string_unprinting() in COMPILE_UTILITY cases.
[exim.git] / src / src / string.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2009 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8 /* Miscellaneous string-handling functions. Some are not required for
9 utilities and tests, and are cut out by the COMPILE_UTILITY macro. */
10
11
12 #include "exim.h"
13
14
15 #ifndef COMPILE_UTILITY
16 /*************************************************
17 *            Test for IP address                 *
18 *************************************************/
19
20 /* This used just to be a regular expression, but with IPv6 things are a bit
21 more complicated. If the address contains a colon, it is assumed to be a v6
22 address (assuming HAVE_IPV6 is set). If a mask is permitted and one is present,
23 and maskptr is not NULL, its offset is placed there.
24
25 Arguments:
26   s         a string
27   maskptr   NULL if no mask is permitted to follow
28             otherwise, points to an int where the offset of '/' is placed
29             if there is no / followed by trailing digits, *maskptr is set 0
30
31 Returns:    0 if the string is not a textual representation of an IP address
32             4 if it is an IPv4 address
33             6 if it is an IPv6 address
34 */
35
36 int
37 string_is_ip_address(uschar *s, int *maskptr)
38 {
39 int i;
40 int yield = 4;
41
42 /* If an optional mask is permitted, check for it. If found, pass back the
43 offset. */
44
45 if (maskptr != NULL)
46   {
47   uschar *ss = s + Ustrlen(s);
48   *maskptr = 0;
49   if (s != ss && isdigit(*(--ss)))
50     {
51     while (ss > s && isdigit(ss[-1])) ss--;
52     if (ss > s && *(--ss) == '/') *maskptr = ss - s;
53     }
54   }
55
56 /* A colon anywhere in the string => IPv6 address */
57
58 if (Ustrchr(s, ':') != NULL)
59   {
60   BOOL had_double_colon = FALSE;
61   BOOL v4end = FALSE;
62   int count = 0;
63
64   yield = 6;
65
66   /* An IPv6 address must start with hex digit or double colon. A single
67   colon is invalid. */
68
69   if (*s == ':' && *(++s) != ':') return 0;
70
71   /* Now read up to 8 components consisting of up to 4 hex digits each. There
72   may be one and only one appearance of double colon, which implies any number
73   of binary zero bits. The number of preceding components is held in count. */
74
75   for (count = 0; count < 8; count++)
76     {
77     /* If the end of the string is reached before reading 8 components, the
78     address is valid provided a double colon has been read. This also applies
79     if we hit the / that introduces a mask or the % that introduces the
80     interface specifier (scope id) of a link-local address. */
81
82     if (*s == 0 || *s == '%' || *s == '/') return had_double_colon? yield : 0;
83
84     /* If a component starts with an additional colon, we have hit a double
85     colon. This is permitted to appear once only, and counts as at least
86     one component. The final component may be of this form. */
87
88     if (*s == ':')
89       {
90       if (had_double_colon) return 0;
91       had_double_colon = TRUE;
92       s++;
93       continue;
94       }
95
96     /* If the remainder of the string contains a dot but no colons, we
97     can expect a trailing IPv4 address. This is valid if either there has
98     been no double-colon and this is the 7th component (with the IPv4 address
99     being the 7th & 8th components), OR if there has been a double-colon
100     and fewer than 6 components. */
101
102     if (Ustrchr(s, ':') == NULL && Ustrchr(s, '.') != NULL)
103       {
104       if ((!had_double_colon && count != 6) ||
105           (had_double_colon && count > 6)) return 0;
106       v4end = TRUE;
107       yield = 6;
108       break;
109       }
110
111     /* Check for at least one and not more than 4 hex digits for this
112     component. */
113
114     if (!isxdigit(*s++)) return 0;
115     if (isxdigit(*s) && isxdigit(*(++s)) && isxdigit(*(++s))) s++;
116
117     /* If the component is terminated by colon and there is more to
118     follow, skip over the colon. If there is no more to follow the address is
119     invalid. */
120
121     if (*s == ':' && *(++s) == 0) return 0;
122     }
123
124   /* If about to handle a trailing IPv4 address, drop through. Otherwise
125   all is well if we are at the end of the string or at the mask or at a percent
126   sign, which introduces the interface specifier (scope id) of a link local
127   address. */
128
129   if (!v4end)
130     return (*s == 0 || *s == '%' ||
131            (*s == '/' && maskptr != NULL && *maskptr != 0))? yield : 0;
132   }
133
134 /* Test for IPv4 address, which may be the tail-end of an IPv6 address. */
135
136 for (i = 0; i < 4; i++)
137   {
138   if (i != 0 && *s++ != '.') return 0;
139   if (!isdigit(*s++)) return 0;
140   if (isdigit(*s) && isdigit(*(++s))) s++;
141   }
142
143 return (*s == 0 || (*s == '/' && maskptr != NULL && *maskptr != 0))?
144   yield : 0;
145 }
146 #endif  /* COMPILE_UTILITY */
147
148
149 /*************************************************
150 *              Format message size               *
151 *************************************************/
152
153 /* Convert a message size in bytes to printing form, rounding
154 according to the magnitude of the number. A value of zero causes
155 a string of spaces to be returned.
156
157 Arguments:
158   size        the message size in bytes
159   buffer      where to put the answer
160
161 Returns:      pointer to the buffer
162               a string of exactly 5 characters is normally returned
163 */
164
165 uschar *
166 string_format_size(int size, uschar *buffer)
167 {
168 if (size == 0) Ustrcpy(CS buffer, "     ");
169 else if (size < 1024) sprintf(CS buffer, "%5d", size);
170 else if (size < 10*1024)
171   sprintf(CS buffer, "%4.1fK", (double)size / 1024.0);
172 else if (size < 1024*1024)
173   sprintf(CS buffer, "%4dK", (size + 512)/1024);
174 else if (size < 10*1024*1024)
175   sprintf(CS buffer, "%4.1fM", (double)size / (1024.0 * 1024.0));
176 else
177   sprintf(CS buffer, "%4dM", (size + 512 * 1024)/(1024*1024));
178 return buffer;
179 }
180
181
182
183 #ifndef COMPILE_UTILITY
184 /*************************************************
185 *       Convert a number to base 62 format       *
186 *************************************************/
187
188 /* Convert a long integer into an ASCII base 62 string. For Cygwin the value of
189 BASE_62 is actually 36. Always return exactly 6 characters plus zero, in a
190 static area.
191
192 Argument: a long integer
193 Returns:  pointer to base 62 string
194 */
195
196 uschar *
197 string_base62(unsigned long int value)
198 {
199 static uschar yield[7];
200 uschar *p = yield + sizeof(yield) - 1;
201 *p = 0;
202 while (p > yield)
203   {
204   *(--p) = base62_chars[value % BASE_62];
205   value /= BASE_62;
206   }
207 return yield;
208 }
209 #endif  /* COMPILE_UTILITY */
210
211
212
213 #ifndef COMPILE_UTILITY
214 /*************************************************
215 *          Interpret escape sequence             *
216 *************************************************/
217
218 /* This function is called from several places where escape sequences are to be
219 interpreted in strings.
220
221 Arguments:
222   pp       points a pointer to the initiating "\" in the string;
223            the pointer gets updated to point to the final character
224 Returns:   the value of the character escape
225 */
226
227 int
228 string_interpret_escape(uschar **pp)
229 {
230 int ch;
231 uschar *p = *pp;
232 ch = *(++p);
233 if (isdigit(ch) && ch != '8' && ch != '9')
234   {
235   ch -= '0';
236   if (isdigit(p[1]) && p[1] != '8' && p[1] != '9')
237     {
238     ch = ch * 8 + *(++p) - '0';
239     if (isdigit(p[1]) && p[1] != '8' && p[1] != '9')
240       ch = ch * 8 + *(++p) - '0';
241     }
242   }
243 else switch(ch)
244   {
245   case 'b':  ch = '\b'; break;
246   case 'f':  ch = '\f'; break;
247   case 'n':  ch = '\n'; break;
248   case 'r':  ch = '\r'; break;
249   case 't':  ch = '\t'; break;
250   case 'v':  ch = '\v'; break;
251   case 'x':
252   ch = 0;
253   if (isxdigit(p[1]))
254     {
255     ch = ch * 16 +
256       Ustrchr(hex_digits, tolower(*(++p))) - hex_digits;
257     if (isxdigit(p[1])) ch = ch * 16 +
258       Ustrchr(hex_digits, tolower(*(++p))) - hex_digits;
259     }
260   break;
261   }
262 *pp = p;
263 return ch;
264 }
265 #endif  /* COMPILE_UTILITY */
266
267
268
269 #ifndef COMPILE_UTILITY
270 /*************************************************
271 *          Ensure string is printable            *
272 *************************************************/
273
274 /* This function is called for critical strings. It checks for any
275 non-printing characters, and if any are found, it makes a new copy
276 of the string with suitable escape sequences. It is most often called by the
277 macro string_printing(), which sets allow_tab TRUE.
278
279 Arguments:
280   s             the input string
281   allow_tab     TRUE to allow tab as a printing character
282
283 Returns:        string with non-printers encoded as printing sequences
284 */
285
286 uschar *
287 string_printing2(uschar *s, BOOL allow_tab)
288 {
289 int nonprintcount = 0;
290 int length = 0;
291 uschar *t = s;
292 uschar *ss, *tt;
293
294 while (*t != 0)
295   {
296   int c = *t++;
297   if (!mac_isprint(c) || (!allow_tab && c == '\t')) nonprintcount++;
298   length++;
299   }
300
301 if (nonprintcount == 0) return s;
302
303 /* Get a new block of store guaranteed big enough to hold the
304 expanded string. */
305
306 ss = store_get(length + nonprintcount * 4 + 1);
307
308 /* Copy everying, escaping non printers. */
309
310 t = s;
311 tt = ss;
312
313 while (*t != 0)
314   {
315   int c = *t;
316   if (mac_isprint(c) && (allow_tab || c != '\t')) *tt++ = *t++; else
317     {
318     *tt++ = '\\';
319     switch (*t)
320       {
321       case '\n': *tt++ = 'n'; break;
322       case '\r': *tt++ = 'r'; break;
323       case '\b': *tt++ = 'b'; break;
324       case '\v': *tt++ = 'v'; break;
325       case '\f': *tt++ = 'f'; break;
326       case '\t': *tt++ = 't'; break;
327       default: sprintf(CS tt, "%03o", *t); tt += 3; break;
328       }
329     t++;
330     }
331   }
332 *tt = 0;
333 return ss;
334 }
335 #endif  /* COMPILE_UTILITY */
336
337
338
339
340 /*************************************************
341 *        Undo printing escapes in string         *
342 *************************************************/
343
344 /* This function is the reverse of string_printing2.  It searches for
345 backslash characters and if any are found, it makes a new copy of the
346 string with escape sequences parsed.  Otherwise it returns the original
347 string.
348
349 Arguments:
350   s             the input string
351
352 Returns:        string with printing escapes parsed back
353 */
354
355 uschar *
356 string_unprinting(uschar *s)
357 {
358 uschar *p, *q, *r, *ss;
359 int len, off;
360
361 p = Ustrchr(s, '\\');
362 if (!p) return s;
363
364 len = Ustrlen(s) + 1;
365 ss = store_get(len);
366
367 q = ss;
368 off = p - s;
369 if (off)
370   {
371   memcpy(q, s, off);
372   q += off;
373   }
374
375 while (*p)
376   {
377   if (*p == '\\')
378     {
379     *q = string_interpret_escape(&p);
380     }
381   else
382     {
383     r = Ustrchr(p, '\\');
384     if (!r)
385       {
386       off = Ustrlen(p);
387       memcpy(q, p, off);
388       p += off;
389       q += off;
390       break;
391       }
392     else
393       {
394       off = r - p;
395       memcpy(q, p, off);
396       q += off;
397       p = r;
398       }
399     }
400   }
401 *q = '\0';
402
403 return ss;
404 }
405
406
407
408
409 /*************************************************
410 *            Copy and save string                *
411 *************************************************/
412
413 /* This function assumes that memcpy() is faster than strcpy().
414
415 Argument: string to copy
416 Returns:  copy of string in new store
417 */
418
419 uschar *
420 string_copy(uschar *s)
421 {
422 int len = Ustrlen(s) + 1;
423 uschar *ss = store_get(len);
424 memcpy(ss, s, len);
425 return ss;
426 }
427
428
429
430 /*************************************************
431 *     Copy and save string in malloc'd store     *
432 *************************************************/
433
434 /* This function assumes that memcpy() is faster than strcpy().
435
436 Argument: string to copy
437 Returns:  copy of string in new store
438 */
439
440 uschar *
441 string_copy_malloc(uschar *s)
442 {
443 int len = Ustrlen(s) + 1;
444 uschar *ss = store_malloc(len);
445 memcpy(ss, s, len);
446 return ss;
447 }
448
449
450
451 /*************************************************
452 *       Copy, lowercase and save string          *
453 *************************************************/
454
455 /*
456 Argument: string to copy
457 Returns:  copy of string in new store, with letters lowercased
458 */
459
460 uschar *
461 string_copylc(uschar *s)
462 {
463 uschar *ss = store_get(Ustrlen(s) + 1);
464 uschar *p = ss;
465 while (*s != 0) *p++ = tolower(*s++);
466 *p = 0;
467 return ss;
468 }
469
470
471
472 /*************************************************
473 *       Copy and save string, given length       *
474 *************************************************/
475
476 /* It is assumed the data contains no zeros. A zero is added
477 onto the end.
478
479 Arguments:
480   s         string to copy
481   n         number of characters
482
483 Returns:    copy of string in new store
484 */
485
486 uschar *
487 string_copyn(uschar *s, int n)
488 {
489 uschar *ss = store_get(n + 1);
490 Ustrncpy(ss, s, n);
491 ss[n] = 0;
492 return ss;
493 }
494
495
496 /*************************************************
497 * Copy, lowercase, and save string, given length *
498 *************************************************/
499
500 /* It is assumed the data contains no zeros. A zero is added
501 onto the end.
502
503 Arguments:
504   s         string to copy
505   n         number of characters
506
507 Returns:    copy of string in new store, with letters lowercased
508 */
509
510 uschar *
511 string_copynlc(uschar *s, int n)
512 {
513 uschar *ss = store_get(n + 1);
514 uschar *p = ss;
515 while (n-- > 0) *p++ = tolower(*s++);
516 *p = 0;
517 return ss;
518 }
519
520
521
522 /*************************************************
523 *    Copy string if long, inserting newlines     *
524 *************************************************/
525
526 /* If the given string is longer than 75 characters, it is copied, and within
527 the copy, certain space characters are converted into newlines.
528
529 Argument:  pointer to the string
530 Returns:   pointer to the possibly altered string
531 */
532
533 uschar *
534 string_split_message(uschar *msg)
535 {
536 uschar *s, *ss;
537
538 if (msg == NULL || Ustrlen(msg) <= 75) return msg;
539 s = ss = msg = string_copy(msg);
540
541 for (;;)
542   {
543   int i = 0;
544   while (i < 75 && *ss != 0 && *ss != '\n') ss++, i++;
545   if (*ss == 0) break;
546   if (*ss == '\n')
547     s = ++ss;
548   else
549     {
550     uschar *t = ss + 1;
551     uschar *tt = NULL;
552     while (--t > s + 35)
553       {
554       if (*t == ' ')
555         {
556         if (t[-1] == ':') { tt = t; break; }
557         if (tt == NULL) tt = t;
558         }
559       }
560
561     if (tt == NULL)          /* Can't split behind - try ahead */
562       {
563       t = ss + 1;
564       while (*t != 0)
565         {
566         if (*t == ' ' || *t == '\n')
567           { tt = t; break; }
568         t++;
569         }
570       }
571
572     if (tt == NULL) break;   /* Can't find anywhere to split */
573     *tt = '\n';
574     s = ss = tt+1;
575     }
576   }
577
578 return msg;
579 }
580
581
582
583 /*************************************************
584 *   Copy returned DNS domain name, de-escaping   *
585 *************************************************/
586
587 /* If a domain name contains top-bit characters, some resolvers return
588 the fully qualified name with those characters turned into escapes. The
589 convention is a backslash followed by _decimal_ digits. We convert these
590 back into the original binary values. This will be relevant when
591 allow_utf8_domains is set true and UTF-8 characters are used in domain
592 names. Backslash can also be used to escape other characters, though we
593 shouldn't come across them in domain names.
594
595 Argument:   the domain name string
596 Returns:    copy of string in new store, de-escaped
597 */
598
599 uschar *
600 string_copy_dnsdomain(uschar *s)
601 {
602 uschar *yield;
603 uschar *ss = yield = store_get(Ustrlen(s) + 1);
604
605 while (*s != 0)
606   {
607   if (*s != '\\')
608     {
609     *ss++ = *s++;
610     }
611   else if (isdigit(s[1]))
612     {
613     *ss++ = (s[1] - '0')*100 + (s[2] - '0')*10 + s[3] - '0';
614     s += 4;
615     }
616   else if (*(++s) != 0)
617     {
618     *ss++ = *s++;
619     }
620   }
621
622 *ss = 0;
623 return yield;
624 }
625
626
627 #ifndef COMPILE_UTILITY
628 /*************************************************
629 *     Copy space-terminated or quoted string     *
630 *************************************************/
631
632 /* This function copies from a string until its end, or until whitespace is
633 encountered, unless the string begins with a double quote, in which case the
634 terminating quote is sought, and escaping within the string is done. The length
635 of a de-quoted string can be no longer than the original, since escaping always
636 turns n characters into 1 character.
637
638 Argument:  pointer to the pointer to the first character, which gets updated
639 Returns:   the new string
640 */
641
642 uschar *
643 string_dequote(uschar **sptr)
644 {
645 uschar *s = *sptr;
646 uschar *t, *yield;
647
648 /* First find the end of the string */
649
650 if (*s != '\"')
651   {
652   while (*s != 0 && !isspace(*s)) s++;
653   }
654 else
655   {
656   s++;
657   while (*s != 0 && *s != '\"')
658     {
659     if (*s == '\\') (void)string_interpret_escape(&s);
660     s++;
661     }
662   if (*s != 0) s++;
663   }
664
665 /* Get enough store to copy into */
666
667 t = yield = store_get(s - *sptr + 1);
668 s = *sptr;
669
670 /* Do the copy */
671
672 if (*s != '\"')
673   {
674   while (*s != 0 && !isspace(*s)) *t++ = *s++;
675   }
676 else
677   {
678   s++;
679   while (*s != 0 && *s != '\"')
680     {
681     if (*s == '\\') *t++ = string_interpret_escape(&s);
682       else *t++ = *s;
683     s++;
684     }
685   if (*s != 0) s++;
686   }
687
688 /* Update the pointer and return the terminated copy */
689
690 *sptr = s;
691 *t = 0;
692 return yield;
693 }
694 #endif  /* COMPILE_UTILITY */
695
696
697
698 /*************************************************
699 *          Format a string and save it           *
700 *************************************************/
701
702 /* The formatting is done by string_format, which checks the length of
703 everything.
704
705 Arguments:
706   format    a printf() format - deliberately char * rather than uschar *
707               because it will most usually be a literal string
708   ...       arguments for format
709
710 Returns:    pointer to fresh piece of store containing sprintf'ed string
711 */
712
713 uschar *
714 string_sprintf(const char *format, ...)
715 {
716 va_list ap;
717 uschar buffer[STRING_SPRINTF_BUFFER_SIZE];
718 va_start(ap, format);
719 if (!string_vformat(buffer, sizeof(buffer), format, ap))
720   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
721     "string_sprintf expansion was longer than %d", sizeof(buffer));
722 va_end(ap);
723 return string_copy(buffer);
724 }
725
726
727
728 /*************************************************
729 *         Case-independent strncmp() function    *
730 *************************************************/
731
732 /*
733 Arguments:
734   s         first string
735   t         second string
736   n         number of characters to compare
737
738 Returns:    < 0, = 0, or > 0, according to the comparison
739 */
740
741 int
742 strncmpic(const uschar *s, const uschar *t, int n)
743 {
744 while (n--)
745   {
746   int c = tolower(*s++) - tolower(*t++);
747   if (c) return c;
748   }
749 return 0;
750 }
751
752
753 /*************************************************
754 *         Case-independent strcmp() function     *
755 *************************************************/
756
757 /*
758 Arguments:
759   s         first string
760   t         second string
761
762 Returns:    < 0, = 0, or > 0, according to the comparison
763 */
764
765 int
766 strcmpic(const uschar *s, const uschar *t)
767 {
768 while (*s != 0)
769   {
770   int c = tolower(*s++) - tolower(*t++);
771   if (c != 0) return c;
772   }
773 return *t;
774 }
775
776
777 /*************************************************
778 *         Case-independent strstr() function     *
779 *************************************************/
780
781 /* The third argument specifies whether whitespace is required
782 to follow the matched string.
783
784 Arguments:
785   s              string to search
786   t              substring to search for
787   space_follows  if TRUE, match only if whitespace follows
788
789 Returns:         pointer to substring in string, or NULL if not found
790 */
791
792 uschar *
793 strstric(uschar *s, uschar *t, BOOL space_follows)
794 {
795 uschar *p = t;
796 uschar *yield = NULL;
797 int cl = tolower(*p);
798 int cu = toupper(*p);
799
800 while (*s)
801   {
802   if (*s == cl || *s == cu)
803     {
804     if (yield == NULL) yield = s;
805     if (*(++p) == 0)
806       {
807       if (!space_follows || s[1] == ' ' || s[1] == '\n' ) return yield;
808       yield = NULL;
809       p = t;
810       }
811     cl = tolower(*p);
812     cu = toupper(*p);
813     s++;
814     }
815   else if (yield != NULL)
816     {
817     yield = NULL;
818     p = t;
819     cl = tolower(*p);
820     cu = toupper(*p);
821     }
822   else s++;
823   }
824 return NULL;
825 }
826
827
828
829 #ifndef COMPILE_UTILITY
830 /*************************************************
831 *       Get next string from separated list      *
832 *************************************************/
833
834 /* Leading and trailing space is removed from each item. The separator in the
835 list is controlled by the int pointed to by the separator argument as follows:
836
837   If the value is > 0 it is used as the separator. This is typically used for
838   sublists such as slash-separated options. The value is always a printing
839   character.
840
841     (If the value is actually > UCHAR_MAX there is only one item in the list.
842     This is used for some cases when called via functions that sometimes
843     plough through lists, and sometimes are given single items.)
844
845   If the value is <= 0, the string is inspected for a leading <x, where x is an
846   ispunct() or an iscntrl() character. If found, x is used as the separator. If
847   not found:
848
849       (a) if separator == 0, ':' is used
850       (b) if separator <0, -separator is used
851
852   In all cases the value of the separator that is used is written back to the
853   int so that it is used on subsequent calls as we progress through the list.
854
855 A literal ispunct() separator can be represented in an item by doubling, but
856 there is no way to include an iscntrl() separator as part of the data.
857
858 Arguments:
859   listptr    points to a pointer to the current start of the list; the
860              pointer gets updated to point after the end of the next item
861   separator  a pointer to the separator character in an int (see above)
862   buffer     where to put a copy of the next string in the list; or
863                NULL if the next string is returned in new memory
864   buflen     when buffer is not NULL, the size of buffer; otherwise ignored
865
866 Returns:     pointer to buffer, containing the next substring,
867              or NULL if no more substrings
868 */
869
870 uschar *
871 string_nextinlist(uschar **listptr, int *separator, uschar *buffer, int buflen)
872 {
873 register int sep = *separator;
874 register uschar *s = *listptr;
875 BOOL sep_is_special;
876
877 if (s == NULL) return NULL;
878
879 /* This allows for a fixed specified separator to be an iscntrl() character,
880 but at the time of implementation, this is never the case. However, it's best
881 to be conservative. */
882
883 while (isspace(*s) && *s != sep) s++;
884
885 /* A change of separator is permitted, so look for a leading '<' followed by an
886 allowed character. */
887
888 if (sep <= 0)
889   {
890   if (*s == '<' && (ispunct(s[1]) || iscntrl(s[1])))
891     {
892     sep = s[1];
893     s += 2;
894     while (isspace(*s) && *s != sep) s++;
895     }
896   else
897     {
898     sep = (sep == 0)? ':' : -sep;
899     }
900   *separator = sep;
901   }
902
903 /* An empty string has no list elements */
904
905 if (*s == 0) return NULL;
906
907 /* Note whether whether or not the separator is an iscntrl() character. */
908
909 sep_is_special = iscntrl(sep);
910
911 /* Handle the case when a buffer is provided. */
912
913 if (buffer != NULL)
914   {
915   register int p = 0;
916   for (; *s != 0; s++)
917     {
918     if (*s == sep && (*(++s) != sep || sep_is_special)) break;
919     if (p < buflen - 1) buffer[p++] = *s;
920     }
921   while (p > 0 && isspace(buffer[p-1])) p--;
922   buffer[p] = 0;
923   }
924
925 /* Handle the case when a buffer is not provided. */
926
927 else
928   {
929   int size = 0;
930   int ptr = 0;
931   uschar *ss;
932
933   /* We know that *s != 0 at this point. However, it might be pointing to a
934   separator, which could indicate an empty string, or (if an ispunct()
935   character) could be doubled to indicate a separator character as data at the
936   start of a string. Avoid getting working memory for an empty item. */
937
938   if (*s == sep)
939     {
940     s++;
941     if (*s != sep || sep_is_special)
942       {
943       *listptr = s;
944       return string_copy(US"");
945       }
946     }
947
948   /* Not an empty string; the first character is guaranteed to be a data
949   character. */
950
951   for (;;)
952     {
953     for (ss = s + 1; *ss != 0 && *ss != sep; ss++);
954     buffer = string_cat(buffer, &size, &ptr, s, ss-s);
955     s = ss;
956     if (*s == 0 || *(++s) != sep || sep_is_special) break;
957     }
958   while (ptr > 0 && isspace(buffer[ptr-1])) ptr--;
959   buffer[ptr] = 0;
960   }
961
962 /* Update the current pointer and return the new string */
963
964 *listptr = s;
965 return buffer;
966 }
967 #endif  /* COMPILE_UTILITY */
968
969
970
971 #ifndef COMPILE_UTILITY
972 /*************************************************
973 *             Add chars to string                *
974 *************************************************/
975
976 /* This function is used when building up strings of unknown length. Room is
977 always left for a terminating zero to be added to the string that is being
978 built. This function does not require the string that is being added to be NUL
979 terminated, because the number of characters to add is given explicitly. It is
980 sometimes called to extract parts of other strings.
981
982 Arguments:
983   string   points to the start of the string that is being built, or NULL
984              if this is a new string that has no contents yet
985   size     points to a variable that holds the current capacity of the memory
986              block (updated if changed)
987   ptr      points to a variable that holds the offset at which to add
988              characters, updated to the new offset
989   s        points to characters to add
990   count    count of characters to add; must not exceed the length of s, if s
991              is a C string
992
993 If string is given as NULL, *size and *ptr should both be zero.
994
995 Returns:   pointer to the start of the string, changed if copied for expansion.
996            Note that a NUL is not added, though space is left for one. This is
997            because string_cat() is often called multiple times to build up a
998            string - there's no point adding the NUL till the end.
999 */
1000
1001 uschar *
1002 string_cat(uschar *string, int *size, int *ptr, const uschar *s, int count)
1003 {
1004 int p = *ptr;
1005
1006 if (p + count >= *size)
1007   {
1008   int oldsize = *size;
1009
1010   /* Mostly, string_cat() is used to build small strings of a few hundred
1011   characters at most. There are times, however, when the strings are very much
1012   longer (for example, a lookup that returns a vast number of alias addresses).
1013   To try to keep things reasonable, we use increments whose size depends on the
1014   existing length of the string. */
1015
1016   int inc = (oldsize < 4096)? 100 : 1024;
1017   while (*size <= p + count) *size += inc;
1018
1019   /* New string */
1020
1021   if (string == NULL) string = store_get(*size);
1022
1023   /* Try to extend an existing allocation. If the result of calling
1024   store_extend() is false, either there isn't room in the current memory block,
1025   or this string is not the top item on the dynamic store stack. We then have
1026   to get a new chunk of store and copy the old string. When building large
1027   strings, it is helpful to call store_release() on the old string, to release
1028   memory blocks that have become empty. (The block will be freed if the string
1029   is at its start.) However, we can do this only if we know that the old string
1030   was the last item on the dynamic memory stack. This is the case if it matches
1031   store_last_get. */
1032
1033   else if (!store_extend(string, oldsize, *size))
1034     {
1035     BOOL release_ok = store_last_get[store_pool] == string;
1036     uschar *newstring = store_get(*size);
1037     memcpy(newstring, string, p);
1038     if (release_ok) store_release(string);
1039     string = newstring;
1040     }
1041   }
1042
1043 /* Because we always specify the exact number of characters to copy, we can
1044 use memcpy(), which is likely to be more efficient than strncopy() because the
1045 latter has to check for zero bytes. */
1046
1047 memcpy(string + p, s, count);
1048 *ptr = p + count;
1049 return string;
1050 }
1051 #endif  /* COMPILE_UTILITY */
1052
1053
1054
1055 #ifndef COMPILE_UTILITY
1056 /*************************************************
1057 *        Append strings to another string        *
1058 *************************************************/
1059
1060 /* This function can be used to build a string from many other strings.
1061 It calls string_cat() to do the dirty work.
1062
1063 Arguments:
1064   string   points to the start of the string that is being built, or NULL
1065              if this is a new string that has no contents yet
1066   size     points to a variable that holds the current capacity of the memory
1067              block (updated if changed)
1068   ptr      points to a variable that holds the offset at which to add
1069              characters, updated to the new offset
1070   count    the number of strings to append
1071   ...      "count" uschar* arguments, which must be valid zero-terminated
1072              C strings
1073
1074 Returns:   pointer to the start of the string, changed if copied for expansion.
1075            The string is not zero-terminated - see string_cat() above.
1076 */
1077
1078 uschar *
1079 string_append(uschar *string, int *size, int *ptr, int count, ...)
1080 {
1081 va_list ap;
1082 int i;
1083
1084 va_start(ap, count);
1085 for (i = 0; i < count; i++)
1086   {
1087   uschar *t = va_arg(ap, uschar *);
1088   string = string_cat(string, size, ptr, t, Ustrlen(t));
1089   }
1090 va_end(ap);
1091
1092 return string;
1093 }
1094 #endif
1095
1096
1097
1098 /*************************************************
1099 *        Format a string with length checks      *
1100 *************************************************/
1101
1102 /* This function is used to format a string with checking of the length of the
1103 output for all conversions. It protects Exim from absent-mindedness when
1104 calling functions like debug_printf and string_sprintf, and elsewhere. There
1105 are two different entry points to what is actually the same function, depending
1106 on whether the variable length list of data arguments are given explicitly or
1107 as a va_list item.
1108
1109 The formats are the usual printf() ones, with some omissions (never used) and
1110 two additions for strings: %S forces lower case, and %#s or %#S prints nothing
1111 for a NULL string. Without the # "NULL" is printed (useful in debugging). There
1112 is also the addition of %D and %M, which insert the date in the form used for
1113 datestamped log files.
1114
1115 Arguments:
1116   buffer       a buffer in which to put the formatted string
1117   buflen       the length of the buffer
1118   format       the format string - deliberately char * and not uschar *
1119   ... or ap    variable list of supplementary arguments
1120
1121 Returns:       TRUE if the result fitted in the buffer
1122 */
1123
1124 BOOL
1125 string_format(uschar *buffer, int buflen, const char *format, ...)
1126 {
1127 BOOL yield;
1128 va_list ap;
1129 va_start(ap, format);
1130 yield = string_vformat(buffer, buflen, format, ap);
1131 va_end(ap);
1132 return yield;
1133 }
1134
1135
1136 BOOL
1137 string_vformat(uschar *buffer, int buflen, const char *format, va_list ap)
1138 {
1139 enum { L_NORMAL, L_SHORT, L_LONG, L_LONGLONG, L_LONGDOUBLE };
1140
1141 BOOL yield = TRUE;
1142 int width, precision;
1143 const char *fp = format;       /* Deliberately not unsigned */
1144 uschar *p = buffer;
1145 uschar *last = buffer + buflen - 1;
1146
1147 string_datestamp_offset = -1;  /* Datestamp not inserted */
1148 string_datestamp_length = 0;   /* Datestamp not inserted */
1149 string_datestamp_type = 0;     /* Datestamp not inserted */
1150
1151 /* Scan the format and handle the insertions */
1152
1153 while (*fp != 0)
1154   {
1155   int length = L_NORMAL;
1156   int *nptr;
1157   int slen;
1158   const char *null = "NULL";   /* ) These variables */
1159   const char *item_start, *s;  /* ) are deliberately */
1160   char newformat[16];          /* ) not unsigned */
1161
1162   /* Non-% characters just get copied verbatim */
1163
1164   if (*fp != '%')
1165     {
1166     if (p >= last) { yield = FALSE; break; }
1167     *p++ = (uschar)*fp++;
1168     continue;
1169     }
1170
1171   /* Deal with % characters. Pick off the width and precision, for checking
1172   strings, skipping over the flag and modifier characters. */
1173
1174   item_start = fp;
1175   width = precision = -1;
1176
1177   if (strchr("-+ #0", *(++fp)) != NULL)
1178     {
1179     if (*fp == '#') null = "";
1180     fp++;
1181     }
1182
1183   if (isdigit((uschar)*fp))
1184     {
1185     width = *fp++ - '0';
1186     while (isdigit((uschar)*fp)) width = width * 10 + *fp++ - '0';
1187     }
1188   else if (*fp == '*')
1189     {
1190     width = va_arg(ap, int);
1191     fp++;
1192     }
1193
1194   if (*fp == '.')
1195     {
1196     if (*(++fp) == '*')
1197       {
1198       precision = va_arg(ap, int);
1199       fp++;
1200       }
1201     else
1202       {
1203       precision = 0;
1204       while (isdigit((uschar)*fp))
1205         precision = precision*10 + *fp++ - '0';
1206       }
1207     }
1208
1209   /* Skip over 'h', 'L', 'l', and 'll', remembering the item length */
1210
1211   if (*fp == 'h')
1212     { fp++; length = L_SHORT; }
1213   else if (*fp == 'L')
1214     { fp++; length = L_LONGDOUBLE; }
1215   else if (*fp == 'l')
1216     {
1217     if (fp[1] == 'l')
1218       {
1219       fp += 2;
1220       length = L_LONGLONG;
1221       }
1222     else
1223       {
1224       fp++;
1225       length = L_LONG;
1226       }
1227     }
1228
1229   /* Handle each specific format type. */
1230
1231   switch (*fp++)
1232     {
1233     case 'n':
1234     nptr = va_arg(ap, int *);
1235     *nptr = p - buffer;
1236     break;
1237
1238     case 'd':
1239     case 'o':
1240     case 'u':
1241     case 'x':
1242     case 'X':
1243     if (p >= last - ((length > L_LONG)? 24 : 12))
1244       { yield = FALSE; goto END_FORMAT; }
1245     strncpy(newformat, item_start, fp - item_start);
1246     newformat[fp - item_start] = 0;
1247
1248     /* Short int is promoted to int when passing through ..., so we must use
1249     int for va_arg(). */
1250
1251     switch(length)
1252       {
1253       case L_SHORT:
1254       case L_NORMAL:   sprintf(CS p, newformat, va_arg(ap, int)); break;
1255       case L_LONG:     sprintf(CS p, newformat, va_arg(ap, long int)); break;
1256       case L_LONGLONG: sprintf(CS p, newformat, va_arg(ap, LONGLONG_T)); break;
1257       }
1258     while (*p) p++;
1259     break;
1260
1261     case 'p':
1262     if (p >= last - 24) { yield = FALSE; goto END_FORMAT; }
1263     strncpy(newformat, item_start, fp - item_start);
1264     newformat[fp - item_start] = 0;
1265     sprintf(CS p, newformat, va_arg(ap, void *));
1266     while (*p) p++;
1267     break;
1268
1269     /* %f format is inherently insecure if the numbers that it may be
1270     handed are unknown (e.g. 1e300). However, in Exim, %f is used for
1271     printing load averages, and these are actually stored as integers
1272     (load average * 1000) so the size of the numbers is constrained.
1273     It is also used for formatting sending rates, where the simplicity
1274     of the format prevents overflow. */
1275
1276     case 'f':
1277     case 'e':
1278     case 'E':
1279     case 'g':
1280     case 'G':
1281     if (precision < 0) precision = 6;
1282     if (p >= last - precision - 8) { yield = FALSE; goto END_FORMAT; }
1283     strncpy(newformat, item_start, fp - item_start);
1284     newformat[fp-item_start] = 0;
1285     if (length == L_LONGDOUBLE)
1286       sprintf(CS p, newformat, va_arg(ap, long double));
1287     else
1288       sprintf(CS p, newformat, va_arg(ap, double));
1289     while (*p) p++;
1290     break;
1291
1292     /* String types */
1293
1294     case '%':
1295     if (p >= last) { yield = FALSE; goto END_FORMAT; }
1296     *p++ = '%';
1297     break;
1298
1299     case 'c':
1300     if (p >= last) { yield = FALSE; goto END_FORMAT; }
1301     *p++ = va_arg(ap, int);
1302     break;
1303
1304     case 'D':                   /* Insert daily datestamp for log file names */
1305     s = CS tod_stamp(tod_log_datestamp_daily);
1306     string_datestamp_offset = p - buffer;   /* Passed back via global */
1307     string_datestamp_length = Ustrlen(s);   /* Passed back via global */
1308     string_datestamp_type = tod_log_datestamp_daily;
1309     slen = string_datestamp_length;
1310     goto INSERT_STRING;
1311
1312     case 'M':                   /* Insert monthly datestamp for log file names */
1313     s = CS tod_stamp(tod_log_datestamp_monthly);
1314     string_datestamp_offset = p - buffer;   /* Passed back via global */
1315     string_datestamp_length = Ustrlen(s);   /* Passed back via global */
1316     string_datestamp_type = tod_log_datestamp_monthly;
1317     slen = string_datestamp_length;
1318     goto INSERT_STRING;
1319
1320     case 's':
1321     case 'S':                   /* Forces *lower* case */
1322     s = va_arg(ap, char *);
1323
1324     if (s == NULL) s = null;
1325     slen = Ustrlen(s);
1326
1327     INSERT_STRING:              /* Come to from %D or %M above */
1328
1329     /* If the width is specified, check that there is a precision
1330     set; if not, set it to the width to prevent overruns of long
1331     strings. */
1332
1333     if (width >= 0)
1334       {
1335       if (precision < 0) precision = width;
1336       }
1337
1338     /* If a width is not specified and the precision is specified, set
1339     the width to the precision, or the string length if shorted. */
1340
1341     else if (precision >= 0)
1342       {
1343       width = (precision < slen)? precision : slen;
1344       }
1345
1346     /* If neither are specified, set them both to the string length. */
1347
1348     else width = precision = slen;
1349
1350     /* Check string space, and add the string to the buffer if ok. If
1351     not OK, add part of the string (debugging uses this to show as
1352     much as possible). */
1353
1354     if (p == last)
1355       {
1356       yield = FALSE;
1357       goto END_FORMAT;
1358       }
1359     if (p >= last - width)
1360       {
1361       yield = FALSE;
1362       width = precision = last - p - 1;
1363       if (width < 0) width = 0;
1364       if (precision < 0) precision = 0;
1365       }
1366     sprintf(CS p, "%*.*s", width, precision, s);
1367     if (fp[-1] == 'S')
1368       while (*p) { *p = tolower(*p); p++; }
1369     else
1370       while (*p) p++;
1371     if (!yield) goto END_FORMAT;
1372     break;
1373
1374     /* Some things are never used in Exim; also catches junk. */
1375
1376     default:
1377     strncpy(newformat, item_start, fp - item_start);
1378     newformat[fp-item_start] = 0;
1379     log_write(0, LOG_MAIN|LOG_PANIC_DIE, "string_format: unsupported type "
1380       "in \"%s\" in \"%s\"", newformat, format);
1381     break;
1382     }
1383   }
1384
1385 /* Ensure string is complete; return TRUE if got to the end of the format */
1386
1387 END_FORMAT:
1388
1389 *p = 0;
1390 return yield;
1391 }
1392
1393
1394
1395 #ifndef COMPILE_UTILITY
1396 /*************************************************
1397 *       Generate an "open failed" message        *
1398 *************************************************/
1399
1400 /* This function creates a message after failure to open a file. It includes a
1401 string supplied as data, adds the strerror() text, and if the failure was
1402 "Permission denied", reads and includes the euid and egid.
1403
1404 Arguments:
1405   eno           the value of errno after the failure
1406   format        a text format string - deliberately not uschar *
1407   ...           arguments for the format string
1408
1409 Returns:        a message, in dynamic store
1410 */
1411
1412 uschar *
1413 string_open_failed(int eno, const char *format, ...)
1414 {
1415 va_list ap;
1416 uschar buffer[1024];
1417
1418 Ustrcpy(buffer, "failed to open ");
1419 va_start(ap, format);
1420
1421 /* Use the checked formatting routine to ensure that the buffer
1422 does not overflow. It should not, since this is called only for internally
1423 specified messages. If it does, the message just gets truncated, and there
1424 doesn't seem much we can do about that. */
1425
1426 (void)string_vformat(buffer+15, sizeof(buffer) - 15, format, ap);
1427
1428 return (eno == EACCES)?
1429   string_sprintf("%s: %s (euid=%ld egid=%ld)", buffer, strerror(eno),
1430     (long int)geteuid(), (long int)getegid()) :
1431   string_sprintf("%s: %s", buffer, strerror(eno));
1432 }
1433 #endif  /* COMPILE_UTILITY */
1434
1435
1436
1437 #ifndef COMPILE_UTILITY
1438 /*************************************************
1439 *        Generate local prt for logging          *
1440 *************************************************/
1441
1442 /* This function is a subroutine for use in string_log_address() below.
1443
1444 Arguments:
1445   addr        the address being logged
1446   yield       the current dynamic buffer pointer
1447   sizeptr     points to current size
1448   ptrptr      points to current insert pointer
1449
1450 Returns:      the new value of the buffer pointer
1451 */
1452
1453 static uschar *
1454 string_get_localpart(address_item *addr, uschar *yield, int *sizeptr,
1455   int *ptrptr)
1456 {
1457 if (testflag(addr, af_include_affixes) && addr->prefix != NULL)
1458   yield = string_cat(yield, sizeptr, ptrptr, addr->prefix,
1459     Ustrlen(addr->prefix));
1460 yield = string_cat(yield, sizeptr, ptrptr, addr->local_part,
1461   Ustrlen(addr->local_part));
1462 if (testflag(addr, af_include_affixes) && addr->suffix != NULL)
1463   yield = string_cat(yield, sizeptr, ptrptr, addr->suffix,
1464     Ustrlen(addr->suffix));
1465 return yield;
1466 }
1467
1468
1469 /*************************************************
1470 *          Generate log address list             *
1471 *************************************************/
1472
1473 /* This function generates a list consisting of an address and its parents, for
1474 use in logging lines. For saved onetime aliased addresses, the onetime parent
1475 field is used. If the address was delivered by a transport with rcpt_include_
1476 affixes set, the af_include_affixes bit will be set in the address. In that
1477 case, we include the affixes here too.
1478
1479 Arguments:
1480   addr          bottom (ultimate) address
1481   all_parents   if TRUE, include all parents
1482   success       TRUE for successful delivery
1483
1484 Returns:        a string in dynamic store
1485 */
1486
1487 uschar *
1488 string_log_address(address_item *addr, BOOL all_parents, BOOL success)
1489 {
1490 int size = 64;
1491 int ptr = 0;
1492 BOOL add_topaddr = TRUE;
1493 uschar *yield = store_get(size);
1494 address_item *topaddr;
1495
1496 /* Find the ultimate parent */
1497
1498 for (topaddr = addr; topaddr->parent != NULL; topaddr = topaddr->parent);
1499
1500 /* We start with just the local part for pipe, file, and reply deliveries, and
1501 for successful local deliveries from routers that have the log_as_local flag
1502 set. File deliveries from filters can be specified as non-absolute paths in
1503 cases where the transport is goin to complete the path. If there is an error
1504 before this happens (expansion failure) the local part will not be updated, and
1505 so won't necessarily look like a path. Add extra text for this case. */
1506
1507 if (testflag(addr, af_pfr) ||
1508       (success &&
1509        addr->router != NULL && addr->router->log_as_local &&
1510        addr->transport != NULL && addr->transport->info->local))
1511   {
1512   if (testflag(addr, af_file) && addr->local_part[0] != '/')
1513     yield = string_cat(yield, &size, &ptr, CUS"save ", 5);
1514   yield = string_get_localpart(addr, yield, &size, &ptr);
1515   }
1516
1517 /* Other deliveries start with the full address. It we have split it into local
1518 part and domain, use those fields. Some early failures can happen before the
1519 splitting is done; in those cases use the original field. */
1520
1521 else
1522   {
1523   if (addr->local_part != NULL)
1524     {
1525     yield = string_get_localpart(addr, yield, &size, &ptr);
1526     yield = string_cat(yield, &size, &ptr, US"@", 1);
1527     yield = string_cat(yield, &size, &ptr, addr->domain,
1528       Ustrlen(addr->domain) );
1529     }
1530   else
1531     {
1532     yield = string_cat(yield, &size, &ptr, addr->address, Ustrlen(addr->address));
1533     }
1534   yield[ptr] = 0;
1535
1536   /* If the address we are going to print is the same as the top address,
1537   and all parents are not being included, don't add on the top address. First
1538   of all, do a caseless comparison; if this succeeds, do a caseful comparison
1539   on the local parts. */
1540
1541   if (strcmpic(yield, topaddr->address) == 0 &&
1542       Ustrncmp(yield, topaddr->address, Ustrchr(yield, '@') - yield) == 0 &&
1543       addr->onetime_parent == NULL &&
1544       (!all_parents || addr->parent == NULL || addr->parent == topaddr))
1545     add_topaddr = FALSE;
1546   }
1547
1548 /* If all parents are requested, or this is a local pipe/file/reply, and
1549 there is at least one intermediate parent, show it in brackets, and continue
1550 with all of them if all are wanted. */
1551
1552 if ((all_parents || testflag(addr, af_pfr)) &&
1553     addr->parent != NULL &&
1554     addr->parent != topaddr)
1555   {
1556   uschar *s = US" (";
1557   address_item *addr2;
1558   for (addr2 = addr->parent; addr2 != topaddr; addr2 = addr2->parent)
1559     {
1560     yield = string_cat(yield, &size, &ptr, s, 2);
1561     yield = string_cat(yield, &size, &ptr, addr2->address, Ustrlen(addr2->address));
1562     if (!all_parents) break;
1563     s = US", ";
1564     }
1565   yield = string_cat(yield, &size, &ptr, US")", 1);
1566   }
1567
1568 /* Add the top address if it is required */
1569
1570 if (add_topaddr)
1571   {
1572   yield = string_cat(yield, &size, &ptr, US" <", 2);
1573
1574   if (addr->onetime_parent == NULL)
1575     yield = string_cat(yield, &size, &ptr, topaddr->address,
1576       Ustrlen(topaddr->address));
1577   else
1578     yield = string_cat(yield, &size, &ptr, addr->onetime_parent,
1579       Ustrlen(addr->onetime_parent));
1580
1581   yield = string_cat(yield, &size, &ptr, US">", 1);
1582   }
1583
1584 yield[ptr] = 0;  /* string_cat() leaves space */
1585 return yield;
1586 }
1587 #endif  /* COMPILE_UTILITY */
1588
1589
1590
1591
1592
1593 /*************************************************
1594 **************************************************
1595 *             Stand-alone test program           *
1596 **************************************************
1597 *************************************************/
1598
1599 #ifdef STAND_ALONE
1600 int main(void)
1601 {
1602 uschar buffer[256];
1603
1604 printf("Testing is_ip_address\n");
1605
1606 while (fgets(CS buffer, sizeof(buffer), stdin) != NULL)
1607   {
1608   int offset;
1609   buffer[Ustrlen(buffer) - 1] = 0;
1610   printf("%d\n", string_is_ip_address(buffer, NULL));
1611   printf("%d %d %s\n", string_is_ip_address(buffer, &offset), offset, buffer);
1612   }
1613
1614 printf("Testing string_nextinlist\n");
1615
1616 while (fgets(CS buffer, sizeof(buffer), stdin) != NULL)
1617   {
1618   uschar *list = buffer;
1619   uschar *lp1, *lp2;
1620   uschar item[256];
1621   int sep1 = 0;
1622   int sep2 = 0;
1623
1624   if (*list == '<')
1625     {
1626     sep1 = sep2 = list[1];
1627     list += 2;
1628     }
1629
1630   lp1 = lp2 = list;
1631   for (;;)
1632     {
1633     uschar *item1 = string_nextinlist(&lp1, &sep1, item, sizeof(item));
1634     uschar *item2 = string_nextinlist(&lp2, &sep2, NULL, 0);
1635
1636     if (item1 == NULL && item2 == NULL) break;
1637     if (item == NULL || item2 == NULL || Ustrcmp(item1, item2) != 0)
1638       {
1639       printf("***ERROR\nitem1=\"%s\"\nitem2=\"%s\"\n",
1640         (item1 == NULL)? "NULL" : CS item1,
1641         (item2 == NULL)? "NULL" : CS item2);
1642       break;
1643       }
1644     else printf("  \"%s\"\n", CS item1);
1645     }
1646   }
1647
1648 /* This is a horrible lash-up, but it serves its purpose. */
1649
1650 printf("Testing string_format\n");
1651
1652 while (fgets(CS buffer, sizeof(buffer), stdin) != NULL)
1653   {
1654   void *args[3];
1655   long long llargs[3];
1656   double dargs[3];
1657   int dflag = 0;
1658   int llflag = 0;
1659   int n = 0;
1660   int count;
1661   int countset = 0;
1662   uschar format[256];
1663   uschar outbuf[256];
1664   uschar *s;
1665   buffer[Ustrlen(buffer) - 1] = 0;
1666
1667   s = Ustrchr(buffer, ',');
1668   if (s == NULL) s = buffer + Ustrlen(buffer);
1669
1670   Ustrncpy(format, buffer, s - buffer);
1671   format[s-buffer] = 0;
1672
1673   if (*s == ',') s++;
1674
1675   while (*s != 0)
1676     {
1677     uschar *ss = s;
1678     s = Ustrchr(ss, ',');
1679     if (s == NULL) s = ss + Ustrlen(ss);
1680
1681     if (isdigit(*ss))
1682       {
1683       Ustrncpy(outbuf, ss, s-ss);
1684       if (Ustrchr(outbuf, '.') != NULL)
1685         {
1686         dflag = 1;
1687         dargs[n++] = Ustrtod(outbuf, NULL);
1688         }
1689       else if (Ustrstr(outbuf, "ll") != NULL)
1690         {
1691         llflag = 1;
1692         llargs[n++] = strtoull(CS outbuf, NULL, 10);
1693         }
1694       else
1695         {
1696         args[n++] = (void *)Uatoi(outbuf);
1697         }
1698       }
1699
1700     else if (Ustrcmp(ss, "*") == 0)
1701       {
1702       args[n++] = (void *)(&count);
1703       countset = 1;
1704       }
1705
1706     else
1707       {
1708       uschar *sss = malloc(s - ss + 1);
1709       Ustrncpy(sss, ss, s-ss);
1710       args[n++] = sss;
1711       }
1712
1713     if (*s == ',') s++;
1714     }
1715
1716   if (!dflag && !llflag)
1717     printf("%s\n", string_format(outbuf, sizeof(outbuf), CS format,
1718       args[0], args[1], args[2])? "True" : "False");
1719
1720   else if (dflag)
1721     printf("%s\n", string_format(outbuf, sizeof(outbuf), CS format,
1722       dargs[0], dargs[1], dargs[2])? "True" : "False");
1723
1724   else printf("%s\n", string_format(outbuf, sizeof(outbuf), CS format,
1725     llargs[0], llargs[1], llargs[2])? "True" : "False");
1726
1727   printf("%s\n", CS outbuf);
1728   if (countset) printf("count=%d\n", count);
1729   }
1730
1731 return 0;
1732 }
1733 #endif
1734
1735 /* End of string.c */