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