]> granicus.if.org Git - strace/blob - error_prints.c
clone: fix print_tls_arg on x86
[strace] / error_prints.c
1 /*
2  * Copyright (c) 1999-2018 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
25 verror_msg(int err_no, const char *fmt, va_list p)
26 {
27         char *msg;
28
29         fflush(NULL);
30
31         /* We want to print entire message with single fprintf to ensure
32          * message integrity if stderr is shared with other programs.
33          * Thus we use vasprintf + single fprintf.
34          */
35         msg = NULL;
36         if (vasprintf(&msg, fmt, p) >= 0) {
37                 if (err_no)
38                         fprintf(stderr, "%s: %s: %s\n",
39                                 program_invocation_name, msg, strerror(err_no));
40                 else
41                         fprintf(stderr, "%s: %s\n",
42                                 program_invocation_name, msg);
43                 free(msg);
44         } else {
45                 /* malloc in vasprintf failed, try it without malloc */
46                 fprintf(stderr, "%s: ", program_invocation_name);
47                 vfprintf(stderr, fmt, p);
48                 if (err_no)
49                         fprintf(stderr, ": %s\n", strerror(err_no));
50                 else
51                         putc('\n', stderr);
52         }
53         /* We don't switch stderr to buffered, thus fprintf(stderr)
54          * always flushes its output and this is not necessary: */
55         /* fflush(stderr); */
56 }
57
58 void
59 error_msg(const char *fmt, ...)
60 {
61         va_list p;
62         va_start(p, fmt);
63         verror_msg(0, fmt, p);
64         va_end(p);
65 }
66
67 void
68 error_msg_and_die(const char *fmt, ...)
69 {
70         va_list p;
71         va_start(p, fmt);
72         verror_msg(0, fmt, p);
73         va_end(p);
74         die();
75 }
76
77 void
78 error_msg_and_help(const char *fmt, ...)
79 {
80         if (fmt != NULL) {
81                 va_list p;
82                 va_start(p, fmt);
83                 verror_msg(0, fmt, p);
84                 va_end(p);
85         }
86         fprintf(stderr, "Try '%s -h' for more information.\n",
87                 program_invocation_name);
88         die();
89 }
90
91 void
92 perror_msg(const char *fmt, ...)
93 {
94         va_list p;
95         va_start(p, fmt);
96         verror_msg(errno, fmt, p);
97         va_end(p);
98 }
99
100 void
101 perror_msg_and_die(const char *fmt, ...)
102 {
103         va_list p;
104         va_start(p, fmt);
105         verror_msg(errno, fmt, p);
106         va_end(p);
107         die();
108 }