Retry only for https protocol
[elinks.git] / src / util / error.c
blobfc83d0eb439ef2540a0d6f67595205f37075798d
1 /** Error handling and debugging stuff
2 * @file */
4 #ifndef _GNU_SOURCE
5 #define _GNU_SOURCE /* Needed for vasprintf() */
6 #endif
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
12 #include <signal.h>
13 #include <stdarg.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h>
19 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_TIME_H
25 #include <time.h>
26 #endif
28 #include "elinks.h"
30 #include "util/error.h"
31 #include "util/lists.h"
32 #include "util/memlist.h"
33 #include "util/memory.h"
34 #include "util/snprintf.h"
35 #include "util/string.h"
38 unsigned char full_static_version[1024] = "ELinks " VERSION_STRING;
40 static void
41 er(int bell, int shall_sleep, unsigned char *fmt, va_list params)
43 if (bell)
44 #ifdef CONFIG_OS_WIN32
45 MessageBeep(MB_ICONEXCLAMATION);
46 #else
47 fputc(7, stderr); /* load and annoying on Windows */
48 #endif
49 vfprintf(stderr, fmt, params);
50 fputc('\n', stderr);
51 fflush(stderr);
52 if (shall_sleep) sleep(1);
55 int errline;
56 const unsigned char *errfile;
58 void
59 elinks_debug(unsigned char *fmt, ...)
61 unsigned char errbuf[4096];
62 va_list params;
64 va_start(params, fmt);
66 snprintf(errbuf, sizeof(errbuf), "DEBUG MESSAGE at %s:%d: %s",
67 errfile, errline, fmt);
69 er(0, 0, errbuf, params);
71 va_end(params);
74 void
75 elinks_wdebug(unsigned char *fmt, ...)
77 unsigned char errbuf[4096];
78 va_list params;
80 va_start(params, fmt);
82 snprintf(errbuf, sizeof(errbuf), "DEBUG MESSAGE at %s:%d: %s",
83 errfile, errline, fmt);
85 er(0, 1, errbuf, params);
87 va_end(params);
90 void
91 elinks_error(unsigned char *fmt, ...)
93 unsigned char errbuf[4096];
94 va_list params;
96 va_start(params, fmt);
98 snprintf(errbuf, sizeof(errbuf), "ERROR at %s:%d: %s",
99 errfile, errline, fmt);
101 er(1, 1, errbuf, params);
103 va_end(params);
106 void
107 elinks_internal(unsigned char *fmt, ...)
109 unsigned char errbuf[4096];
110 va_list params;
112 va_start(params, fmt);
114 snprintf(errbuf, sizeof(errbuf),
115 "\033[1mINTERNAL ERROR\033[0m at %s:%d: %s",
116 errfile, errline, fmt);
118 er(1, 1, errbuf, params);
120 va_end(params);
121 #ifdef CONFIG_DEBUG
122 force_dump();
123 #endif
127 void
128 usrerror(unsigned char *fmt, ...)
130 va_list params;
132 va_start(params, fmt);
134 fputs("ELinks: ", stderr);
135 vfprintf(stderr, fmt, params);
136 fputc('\n', stderr);
137 fflush(stderr);
139 va_end(params);
143 int assert_failed = 0;
145 void
146 elinks_assertm(int x, unsigned char *fmt, ...)
148 unsigned char *buf = NULL;
149 va_list params;
151 if (assert_failed) return;
152 if (!(assert_failed = !x)) return;
154 va_start(params, fmt);
155 vasprintf((char **) &buf, fmt, params);
156 va_end(params);
157 elinks_internal("assertion failed: %s", buf);
158 if (buf) free(buf);
162 #ifdef CONFIG_DEBUG
163 void
164 force_dump(void)
166 fprintf(stderr,
167 "\n\033[1m%s\033[0m %s\n", "Forcing core dump!",
168 "Man the Lifeboats! Women and children first!\n");
169 fputs("But please DO NOT report this as a segfault!!! It is an internal error, not a\n"
170 "normal segfault, there is a huge difference in these for us the developers.\n"
171 "Also, noting the EXACT error you got above is crucial for hunting the problem\n"
172 "down. Thanks, and please get in touch with us.\n",
173 stderr);
174 #ifndef CONFIG_BACKTRACE
175 fputs(full_static_version, stderr);
176 fputc('\n', stderr);
177 #endif
178 fflush(stderr);
179 raise(SIGSEGV);
182 static FILE *log_file = NULL;
184 static void
185 done_log(void)
187 unsigned char errbuf[4096];
188 time_t curtime = time(NULL);
189 struct tm *loctime = localtime(&curtime);
190 int len;
192 len = strftime(errbuf, sizeof(errbuf), "%a, %d %b %Y %H:%M:%S %z",
193 loctime);
194 errbuf[len] = '\0';
196 fprintf(log_file, "[%-5s %-15s %4s]: Log stopped at %s\n\n\n",
197 "", "", "", errbuf);
199 fclose(log_file);
202 void
203 elinks_log(unsigned char *msg, unsigned char *file, int line,
204 unsigned char *fmt, ...)
206 static unsigned char *log_files = NULL;
207 static unsigned char *log_msg = NULL;
208 unsigned char errbuf[4096];
209 va_list params;
211 if (!log_file) {
212 unsigned char *log_name;
213 time_t curtime = time(NULL);
214 struct tm *loctime = localtime(&curtime);
215 int len;
217 log_files = getenv("ELINKS_FILES");
218 log_msg = getenv("ELINKS_MSG");
219 log_name = getenv("ELINKS_LOG");
220 log_file = log_name ? fopen(log_name, "ab") : stderr;
222 if (!log_file) return;
224 len = strftime(errbuf, sizeof(errbuf), "%a, %d %b %Y %H:%M:%S %z",
225 loctime);
226 errbuf[len] = '\0';
228 fprintf(log_file, "\n\n[%-5s %-15s %4s]: Log started at %s\n",
229 "type", "file", "line", errbuf);
231 atexit(done_log);
234 if (log_files && !strstr((const char *)log_files, file))
235 return;
237 if (log_msg && !strstr((const char *)log_msg, msg))
238 return;
240 va_start(params, fmt);
242 snprintf(errbuf, sizeof(errbuf), "[%-5s %-15s %4d]: %s",
243 msg, file, line, fmt);
245 vfprintf(log_file, errbuf, params);
246 fputc('\n', log_file);
247 fflush(log_file);
249 va_end(params);
251 #endif
254 void
255 do_not_optimize_here(void *p)
257 /* stop GCC optimization - avoid bugs in it */
261 #ifdef CONFIG_BACKTRACE
263 /* The backtrace corner. */
265 #include <stdio.h>
266 #include <stdlib.h>
268 #ifdef HAVE_EXECINFO_H
269 #include <execinfo.h>
270 #endif
272 void
273 dump_backtrace(FILE *f, int trouble)
275 /* If trouble is set, when we get here, we can be in various
276 * interesting situations like inside of the SIGSEGV handler etc. So be
277 * especially careful here. Dynamic memory allocation may not work
278 * (corrupted stack). A lot of other things may not work too. So better
279 * don't do anything not 100% necessary. */
281 #ifdef HAVE_EXECINFO_H
282 /* glibc way of doing this */
284 void *stack[20];
285 size_t size;
286 char **strings;
287 size_t i;
289 size = backtrace(stack, 20);
291 if (trouble) {
292 /* Let's hope fileno() is safe. */
293 backtrace_symbols_fd(stack, size, fileno(f));
294 /* Now out! */
295 return;
298 strings = backtrace_symbols(stack, size);
300 fprintf(f, "Obtained %d stack frames:\n", (int) size);
302 for (i = 0; i < size; i++)
303 fprintf(f, "[%p] %s\n", stack[i], strings[i]);
305 free(strings);
307 #else
308 /* User torturation. */
309 /* You are worried about what you see here? You don't see anything in
310 * the first place. Also, be assured that we know what are we doing. */
311 /* (We are killing the user, obviously.) */
313 /* TODO: Gettextify? Er, better not. More people (translators) could
314 * find out what are we doing... ;-) --pasky */
315 /* TODO: Be more cruel when in trouble? ;-) --pasky */
317 fputs( "Wheeeeeeeeeee! You played with the config.h by hand, didn't you?\n"
318 "Of _COURSE_ you did! Is that how a nice .. creature behaves like?\n"
319 "Of _COURSE_ it isn't! I feel offended and thus I will revenge now!\n"
320 "You will _suffer_ >:).\n"
321 "\n"
322 "CPU burning sequence initiated...\n", f);
324 /* TODO: Include cpuburn.c here. --pasky */
325 while (1);
326 #endif
327 fflush(f);
330 #endif