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