1c1f2dd83304cb2b65712b5d73c75b8fabb43c70
[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 */