+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcat", CUS func, line);
+#endif
+return US strcat(CS dst, CCS src);
+}
+static inline uschar * __Ustrcpy(uschar * dst, const uschar * src, const char * func, int line)
+{
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcpy", CUS func, line);
+#endif
+return US strcpy(CS dst, CCS src);
+}
+static inline uschar * __Ustrncat(uschar * dst, const uschar * src, size_t n, const char * func, int line)
+{
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncat", CUS func, line);
+#endif
+return US strncat(CS dst, CCS src, n);
+}
+static inline uschar * __Ustrncpy(uschar * dst, const uschar * src, size_t n, const char * func, int line)
+{
+#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
+if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncpy", CUS func, line);
+#endif
+return US strncpy(CS dst, CCS src, n);
+}
+/*XXX will likely need unchecked copy also */
+
+
+/******************************************************************************/
+
+#if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
+/* exim_chown - in some NFSv4 setups *seemes* to be an issue with
+chown(<exim-uid>, <exim-gid>).
+
+Probably because the idmapping is broken, misconfigured or set up in
+an unusal way. (see Bug 2931). As I'm not sure, if this was a single
+case of misconfiguration, or if there are more such broken systems
+out, I try to impose as least impact as possible and for now just write
+a panic log entry pointing to the bug report. You're encouraged to
+contact the developers, if you experience this issue.
+
+fd the file descriptor (or -1 if not valid)
+name the file name for error messages or for file operations,
+ if fd is < 0
+owner the owner
+group the group
+
+returns 0 on success, -1 on failure */
+
+static inline int
+exim_fchown(int fd, uid_t owner, gid_t group, const uschar *name)
+{
+return fchown(fd, owner, group)
+ ? exim_chown_failure(fd, name, owner, group) : 0;
+}
+
+static inline int
+exim_chown(const uschar *name, uid_t owner, gid_t group)
+{
+return chown(CCS name, owner, group)
+ ? exim_chown_failure(-1, name, owner, group) : 0;
+}
+#endif /* !MACRO_PREDEF && !COMPILE_UTILITY */
+
+/******************************************************************************/
+/* String functions */
+
+#if !defined(MACRO_PREDEF)
+/*************************************************
+* Copy and save string *
+*************************************************/
+
+/* This function assumes that memcpy() is faster than strcpy().
+*/
+
+static inline uschar *
+string_copy_taint_trc(const uschar *s, BOOL tainted, const char * func, int line)
+{
+int len = Ustrlen(s) + 1;
+uschar *ss = store_get_3(len, tainted, func, line);
+memcpy(ss, s, len);
+return ss;
+}
+
+#define string_copy_taint(s, tainted) \
+ string_copy_taint_trc((s), tainted, __FUNCTION__, __LINE__)
+
+static inline uschar *
+string_copy_trc(const uschar * s, const char * func, int line)
+{
+return string_copy_taint_trc((s), is_tainted(s), func, line);
+}
+
+#define string_copy(s) \
+ string_copy_trc((s), __FUNCTION__, __LINE__)
+
+
+/*************************************************
+* Copy, lowercase and save string *
+*************************************************/
+
+/*
+Argument: string to copy
+Returns: copy of string in new store, with letters lowercased
+*/
+
+static inline uschar *
+string_copylc(const uschar *s)
+{
+uschar *ss = store_get(Ustrlen(s) + 1, is_tainted(s));
+uschar *p = ss;
+while (*s != 0) *p++ = tolower(*s++);
+*p = 0;
+return ss;
+}
+
+
+
+/*************************************************
+* Copy and save string, given length *
+*************************************************/
+
+/* It is assumed the data contains no zeros. A zero is added
+onto the end.
+
+Arguments:
+ s string to copy
+ n number of characters
+
+Returns: copy of string in new store
+
+This is an API for local_scan hence not static.
+*/
+
+static inline uschar *
+string_copyn(const uschar *s, int n)
+{
+uschar *ss = store_get(n + 1, is_tainted(s));
+Ustrncpy(ss, s, n);
+ss[n] = 0;
+return ss;
+}
+
+/*************************************************
+* Copy, lowercase, and save string, given length *
+*************************************************/
+
+/* It is assumed the data contains no zeros. A zero is added
+onto the end.
+
+Arguments:
+ s string to copy
+ n number of characters
+
+Returns: copy of string in new store, with letters lowercased
+*/
+
+static inline uschar *
+string_copynlc(uschar *s, int n)
+{
+uschar *ss = store_get(n + 1, is_tainted(s));
+uschar *p = ss;
+while (n-- > 0) *p++ = tolower(*s++);
+*p = 0;
+return ss;
+}
+
+
+# ifndef COMPILE_UTILITY
+/*************************************************
+* Copy and save string in longterm store *
+*************************************************/
+
+/* This function assumes that memcpy() is faster than strcpy().
+
+Argument: string to copy
+Returns: copy of string in new store
+*/
+
+static inline uschar *
+string_copy_perm(const uschar *s, BOOL force_taint)
+{
+int old_pool = store_pool;
+int len = Ustrlen(s) + 1;
+uschar *ss;
+
+store_pool = POOL_PERM;
+ss = store_get(len, force_taint || is_tainted(s));
+memcpy(ss, s, len);
+store_pool = old_pool;
+return ss;
+}
+# endif
+
+
+
+/* sprintf into a buffer, taint-unchecked */
+
+static inline void
+string_format_nt(uschar * buf, int siz, const char * fmt, ...)
+{
+gstring gs = { .size = siz, .ptr = 0, .s = buf };
+va_list ap;
+va_start(ap, fmt);
+(void) string_vformat(&gs, SVFMT_TAINT_NOCHK, fmt, ap);
+va_end(ap);
+}
+
+
+
+/******************************************************************************/
+/* Growable-string functions */