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