1 /*
2 * Copyright (c) 1999-2022 The strace developers.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8 #ifdef HAVE_CONFIG_H
9 # include "config.h"
10 #endif
11
12 #include <errno.h>
13 #include <stdarg.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #include "error_prints.h"
19
20 #ifndef HAVE_PROGRAM_INVOCATION_NAME
21 extern char *program_invocation_name;
22 #endif
23
24 static void ATTRIBUTE_FORMAT((__printf__, 2, 0))
25 verror_msg(int err_no, const char *fmt, va_list p)
26 {
27 char *msg;
28
29 fflush(NULL);
30
31 /*
32 * We want to print the entire message with a single fprintf to ensure
33 * the message integrity if stderr is shared with other programs.
34 * Thus we use vasprintf + single fprintf.
35 */
36 msg = NULL;
37 if (vasprintf(&msg, fmt, p) >= 0) {
38 if (err_no)
39 fprintf(stderr, "%s: %s: %s\n",
40 program_invocation_name, msg, strerror(err_no));
41 else
42 fprintf(stderr, "%s: %s\n",
43 program_invocation_name, msg);
44 free(msg);
45 } else {
46 /* malloc in vasprintf failed, try it without malloc */
47 fprintf(stderr, "%s: ", program_invocation_name);
48 vfprintf(stderr, fmt, p);
49 if (err_no)
50 fprintf(stderr, ": %s\n", strerror(err_no));
51 else
52 putc('\n', stderr);
53 }
54 /*
55 * We don't switch stderr to buffered, thus fprintf(stderr)
56 * always flushes its output and this is not necessary:
57 * fflush(stderr);
58 */
59 }
60
61 void
62 error_msg(const char *fmt, ...)
63 {
64 va_list p;
65 va_start(p, fmt);
66 verror_msg(0, fmt, p);
67 va_end(p);
68 }
69
70 void
71 error_msg_and_die(const char *fmt, ...)
72 {
73 va_list p;
74 va_start(p, fmt);
75 verror_msg(0, fmt, p);
76 va_end(p);
77 die();
78 }
79
80 void
81 error_msg_and_help(const char *fmt, ...)
82 {
83 if (fmt != NULL) {
84 va_list p;
85 va_start(p, fmt);
86 verror_msg(0, fmt, p);
87 va_end(p);
88 }
89 fprintf(stderr, "Try '%s -h' for more information.\n",
90 program_invocation_name);
91 die();
92 }
93
94 void
95 perror_msg(const char *fmt, ...)
96 {
97 va_list p;
98 va_start(p, fmt);
99 verror_msg(errno, fmt, p);
100 va_end(p);
101 }
102
103 void
104 perror_msg_and_die(const char *fmt, ...)
105 {
106 va_list p;
107 va_start(p, fmt);
108 verror_msg(errno, fmt, p);
109 va_end(p);
110 die();
111 }