1 /*
2 * Close stdin, move stdout to a non-standard descriptor, and print.
3 *
4 * Copyright (c) 2016-2021 Dmitry V. Levin <ldv@strace.io>
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11
12 #include <assert.h>
13 #include <errno.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <unistd.h>
17
18 static ssize_t
19 write_retry(int fd, const void *buf, size_t count)
20 {
21 ssize_t rc;
22
23 do {
24 errno = 0;
25 rc = write(fd, buf, count);
26 } while (rc == -1 && EINTR == errno);
27
28 if (rc <= 0)
29 perror_msg_and_fail("write");
30
31 return rc;
32 }
33
34 static void
35 write_loop(int fd, const char *buf, size_t count)
36 {
37 ssize_t offset = 0;
38
39 while (count > 0) {
40 ssize_t block = write_retry(fd, &buf[offset], count);
41
42 offset += block;
43 count -= (size_t) block;
44 }
45 }
46
47 void
48 tprintf(const char *fmt, ...)
49 {
50 static int initialized;
51 if (!initialized) {
52 assert(dup2(1, 3) == 3);
53 assert(close(1) == 0);
54 (void) close(0);
55 initialized = 1;
56 }
57
58 va_list p;
59 va_start(p, fmt);
60
61 static char buf[65536];
62 int len = vsnprintf(buf, sizeof(buf), fmt, p);
63 if (len < 0)
64 perror_msg_and_fail("vsnprintf");
65 assert((unsigned) len < sizeof(buf));
66
67 write_loop(3, buf, len);
68
69 va_end(p);
70 }