Line | Count | Source (jump to first uncovered line) |
1 | | /* msg.cpp -- info and error messages |
2 | | |
3 | | This file is part of the UPX executable compressor. |
4 | | |
5 | | Copyright (C) 1996-2025 Markus Franz Xaver Johannes Oberhumer |
6 | | Copyright (C) 1996-2025 Laszlo Molnar |
7 | | All Rights Reserved. |
8 | | |
9 | | UPX and the UCL library are free software; you can redistribute them |
10 | | and/or modify them under the terms of the GNU General Public License as |
11 | | published by the Free Software Foundation; either version 2 of |
12 | | the License, or (at your option) any later version. |
13 | | |
14 | | This program is distributed in the hope that it will be useful, |
15 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | GNU General Public License for more details. |
18 | | |
19 | | You should have received a copy of the GNU General Public License |
20 | | along with this program; see the file COPYING. |
21 | | If not, write to the Free Software Foundation, Inc., |
22 | | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
23 | | |
24 | | Markus F.X.J. Oberhumer Laszlo Molnar |
25 | | <markus@oberhumer.com> <ezerotven+github@gmail.com> |
26 | | */ |
27 | | |
28 | | #include "util/system_headers.h" |
29 | | #include <typeinfo> // typeid() |
30 | | #include "conf.h" |
31 | | |
32 | | /************************************************************************* |
33 | | // |
34 | | **************************************************************************/ |
35 | | |
36 | | static int pr_need_nl = 0; |
37 | | |
38 | 24.5k | void printSetNl(int need_nl) noexcept { pr_need_nl = need_nl; } |
39 | | |
40 | 118 | void printClearLine(FILE *f) noexcept { |
41 | 118 | static char clear_line_msg[1 + 79 + 1 + 1]; |
42 | 118 | if (!clear_line_msg[0]) { |
43 | 1 | char *msg = clear_line_msg; |
44 | 1 | msg[0] = '\r'; |
45 | 1 | memset(msg + 1, ' ', 79); |
46 | 1 | msg[80] = '\r'; |
47 | 1 | msg[81] = 0; |
48 | 1 | } |
49 | | |
50 | 118 | fflush(stdout); |
51 | 118 | fflush(stderr); |
52 | 118 | if (f == nullptr) |
53 | 0 | f = stdout; |
54 | 118 | con_fprintf(f, "%s", clear_line_msg); // NOLINT(clang-analyzer-unix.Stream) |
55 | 118 | fflush(f); |
56 | 118 | printSetNl(0); |
57 | 118 | } |
58 | | |
59 | 101k | static void pr_print(bool c, const char *msg) noexcept { |
60 | 101k | if (c && !opt->to_stdout) |
61 | 0 | con_fprintf(stderr, "%s", msg); |
62 | 101k | else |
63 | 101k | fprintf(stderr, "%s", msg); |
64 | 101k | } |
65 | | |
66 | 25.4k | static void pr_error(const char *iname, const char *msg, bool is_warning) noexcept { |
67 | 25.4k | fflush(stdout); |
68 | 25.4k | fflush(stderr); |
69 | 25.4k | char buf[1024]; |
70 | 25.4k | buf[0] = 0; |
71 | 25.4k | if (pr_need_nl == 2) |
72 | 0 | printClearLine(stdout); |
73 | 25.4k | else if (pr_need_nl) { |
74 | 2.44k | buf[0] = '\n'; |
75 | 2.44k | buf[1] = 0; |
76 | 2.44k | printSetNl(0); |
77 | 2.44k | } |
78 | | |
79 | | // This hack is needed, otherwise error messages may get lost |
80 | | // when the cursor is not yet at the bottom of the screen. |
81 | | // At least I can use some colors then... |
82 | 25.4k | bool c = acc_isatty(STDERR_FILENO) ? 1 : 0; |
83 | | |
84 | 25.4k | int fg = con_fg(stderr, FG_BRTRED); |
85 | 25.4k | upx_safe_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s: ", progname); |
86 | 25.4k | pr_print(c, buf); |
87 | | //(void)con_fg(stderr,FG_RED); |
88 | 25.4k | upx_safe_snprintf(buf, sizeof(buf), "%s: ", iname); |
89 | 25.4k | pr_print(c, buf); |
90 | | //(void)con_fg(stderr,FG_BRTRED); |
91 | 25.4k | pr_print(c, msg); |
92 | 25.4k | pr_print(c, "\n"); |
93 | 25.4k | fflush(stdout); |
94 | 25.4k | fflush(stderr); |
95 | 25.4k | fg = con_fg(stderr, fg); |
96 | | |
97 | 25.4k | UNUSED(is_warning); |
98 | 25.4k | UNUSED(fg); |
99 | 25.4k | } |
100 | | |
101 | 25.4k | void printErr(const char *iname, const Throwable &e) noexcept { |
102 | 25.4k | char buf[1024]; |
103 | 25.4k | size_t l; |
104 | | |
105 | 25.4k | upx_safe_snprintf(buf, sizeof(buf), "%s", prettyExceptionName(typeid(e).name())); |
106 | 25.4k | l = strlen(buf); |
107 | 25.4k | if (l < sizeof(buf) && e.getMsg()) |
108 | 25.4k | upx_safe_snprintf(buf + l, sizeof(buf) - l, ": %s", e.getMsg()); |
109 | 25.4k | l = strlen(buf); |
110 | 25.4k | if (l < sizeof(buf) && e.getErrno()) { |
111 | 0 | upx_safe_snprintf(buf + l, sizeof(buf) - l, ": %s", strerror(e.getErrno())); |
112 | 0 | #if 1 |
113 | | // some compilers (e.g. Borland C++) put a trailing '\n' |
114 | | // into the strerror() result |
115 | 0 | l = strlen(buf); |
116 | 0 | while (l-- > 0 && (buf[l] == '\n' || buf[l] == ' ')) |
117 | 0 | buf[l] = 0; |
118 | 0 | #endif |
119 | 0 | } |
120 | 25.4k | pr_error(iname, buf, e.isWarning()); |
121 | 25.4k | } |
122 | | |
123 | 0 | void printErr(const char *iname, const char *format, ...) noexcept { |
124 | 0 | va_list args; |
125 | 0 | char buf[1024]; |
126 | |
|
127 | 0 | va_start(args, format); |
128 | 0 | upx_safe_vsnprintf(buf, sizeof(buf), format, args); |
129 | 0 | va_end(args); |
130 | |
|
131 | 0 | pr_error(iname, buf, false); |
132 | 0 | } |
133 | | |
134 | 0 | void printWarn(const char *iname, const char *format, ...) noexcept { |
135 | 0 | va_list args; |
136 | 0 | char buf[1024]; |
137 | |
|
138 | 0 | va_start(args, format); |
139 | 0 | upx_safe_vsnprintf(buf, sizeof(buf), format, args); |
140 | 0 | va_end(args); |
141 | |
|
142 | 0 | pr_error(iname, buf, true); |
143 | 0 | } |
144 | | |
145 | 0 | void printUnhandledException(const char *iname, const std::exception *e) noexcept { |
146 | 0 | if (e != nullptr) |
147 | 0 | printErr(iname, "unhandled exception: %s\n", prettyExceptionName(e->what())); |
148 | 0 | else |
149 | 0 | printErr(iname, "internal error: unhandled exception!\n"); |
150 | 0 | if (opt->cmd != CMD_COMPRESS) { |
151 | 0 | printErr(iname, " this file has possibly been modified/hacked; take care!\n"); |
152 | 0 | } |
153 | 0 | } |
154 | | |
155 | | /************************************************************************* |
156 | | // info |
157 | | **************************************************************************/ |
158 | | |
159 | | static int info_header = 0; |
160 | | |
161 | 1.45k | static void info_print(const char *msg) { |
162 | 1.45k | if (opt->info_mode <= 0) |
163 | 0 | return; |
164 | 1.45k | FILE *f = opt->to_stdout ? stderr : stdout; |
165 | 1.45k | if (pr_need_nl) { |
166 | 118 | printClearLine(f); |
167 | 118 | con_fprintf(f, "%s\n", msg); |
168 | 1.34k | } else if (pr_need_nl) |
169 | 0 | con_fprintf(f, "\n%s\n", msg); |
170 | 1.34k | else |
171 | 1.34k | con_fprintf(f, "%s\n", msg); |
172 | 1.45k | fflush(f); |
173 | 1.45k | printSetNl(0); |
174 | 1.45k | } |
175 | | |
176 | 25.7k | void infoHeader() { info_header = 0; } |
177 | | |
178 | 20 | void infoHeader(const char *format, ...) { |
179 | 20 | if (opt->info_mode <= 0) |
180 | 20 | return; |
181 | 0 | va_list args; |
182 | 0 | char buf[1024]; |
183 | 0 | va_start(args, format); |
184 | 0 | upx_safe_vsnprintf(buf, sizeof(buf), format, args); |
185 | 0 | va_end(args); |
186 | 0 | info_print(buf); |
187 | 0 | info_header = 1; |
188 | 0 | } |
189 | | |
190 | 1.65k | void info(const char *format, ...) { |
191 | 1.65k | if (opt->info_mode <= 0) |
192 | 192 | return; |
193 | 1.45k | va_list args; |
194 | 1.45k | char buf[1024]; |
195 | 1.45k | const int n = 4 * info_header; |
196 | 1.45k | memset(buf, ' ', n); |
197 | 1.45k | va_start(args, format); |
198 | 1.45k | upx_safe_vsnprintf(buf + n, sizeof(buf) - n, format, args); |
199 | 1.45k | va_end(args); |
200 | 1.45k | info_print(buf); |
201 | 1.45k | } |
202 | | |
203 | 3.34k | void infoWarning(const char *format, ...) { |
204 | 3.34k | if (opt->info_mode <= 0) |
205 | 1.88k | return; |
206 | 1.45k | va_list args; |
207 | 1.45k | char buf[1024]; |
208 | 1.45k | va_start(args, format); |
209 | 1.45k | upx_safe_vsnprintf(buf, sizeof(buf), format, args); |
210 | 1.45k | va_end(args); |
211 | 1.45k | info("[WARNING] %s\n", buf); |
212 | 1.45k | } |
213 | | |
214 | 0 | void infoWriting(const char *what, upx_int64_t size) { |
215 | 0 | if (opt->info_mode <= 0) |
216 | 0 | return; |
217 | 0 | info("Writing %s: %lld bytes", what, size); |
218 | 0 | } |
219 | | |
220 | | /* vim:set ts=4 sw=4 et: */ |