po: Update German man pages translation
[dpkg.git] / lib / dpkg / ehandle.c
blobbe95c364239319daa2feafde6373d9b34c892ea4
1 /*
2 * libdpkg - Debian packaging suite library routines
3 * ehandle.c - error handling
5 * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
8 * This is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 #include <config.h>
23 #include <compat.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <stdio.h>
32 #include <dpkg/macros.h>
33 #include <dpkg/i18n.h>
34 #include <dpkg/progname.h>
35 #include <dpkg/color.h>
36 #include <dpkg/ehandle.h>
38 /* Incremented when we do some kind of generally necessary operation,
39 * so that loops &c know to quit if we take an error exit. Decremented
40 * again afterwards. */
41 volatile int onerr_abort = 0;
43 #define NCALLS 2
45 struct cleanup_entry {
46 struct cleanup_entry *next;
47 struct {
48 int mask;
49 void (*call)(int argc, void **argv);
50 } calls[NCALLS];
51 int cpmask, cpvalue;
52 int argc;
53 void *argv[1];
56 struct error_context {
57 struct error_context *next;
59 enum {
60 HANDLER_TYPE_FUNC,
61 HANDLER_TYPE_JUMP,
62 } handler_type;
64 union {
65 error_handler_func *func;
66 jmp_buf *jump;
67 } handler;
69 struct {
70 error_printer_func *func;
71 const void *data;
72 } printer;
74 struct cleanup_entry *cleanups;
76 char *errmsg;
79 static struct error_context *volatile econtext = NULL;
81 /**
82 * Emergency variables.
84 * These are used when the system is out of resources, and we want to be able
85 * to proceed anyway at least to the point of a controlled shutdown.
87 static struct {
88 struct cleanup_entry ce;
89 void *args[20];
91 /**
92 * Emergency error message buffer.
94 * The size is estimated using the following heuristic:
95 * - 6x255 For inserted strings (%.255s &c in fmt; and %s with limited
96 * length arg).
97 * - 1x255 For constant text.
98 * - 1x255 For strerror().
99 * - And the total doubled just in case.
101 char errmsg[4096];
102 } emergency;
105 * Default fatal error handler.
107 * This handler performs all error unwinding for the current context, and
108 * terminates the program with an error exit code.
110 void
111 catch_fatal_error(void)
113 pop_error_context(ehflag_bombout);
114 exit(2);
117 void
118 print_fatal_error(const char *emsg, const void *data)
120 fprintf(stderr, "%s%s:%s %s%s:%s %s\n",
121 color_get(COLOR_PROG), dpkg_get_progname(), color_reset(),
122 color_get(COLOR_ERROR), _("error"), color_reset(), emsg);
125 static void
126 print_abort_error(const char *etype, const char *emsg)
128 fprintf(stderr, _("%s%s%s: %s%s:%s\n %s\n"),
129 color_get(COLOR_PROG), dpkg_get_progname(), color_reset(),
130 color_get(COLOR_ERROR), etype, color_reset(), emsg);
133 static struct error_context *
134 error_context_new(void)
136 struct error_context *necp;
138 necp = malloc(sizeof(*necp));
139 if (!necp)
140 ohshite(_("out of memory for new error context"));
141 necp->next= econtext;
142 necp->cleanups= NULL;
143 necp->errmsg = NULL;
144 econtext= necp;
146 return necp;
149 static void
150 set_error_printer(struct error_context *ec, error_printer_func *func,
151 const void *data)
153 ec->printer.func = func;
154 ec->printer.data = data;
157 static void
158 set_func_handler(struct error_context *ec, error_handler_func *func)
160 ec->handler_type = HANDLER_TYPE_FUNC;
161 ec->handler.func = func;
164 static void
165 set_jump_handler(struct error_context *ec, jmp_buf *jump)
167 ec->handler_type = HANDLER_TYPE_JUMP;
168 ec->handler.jump = jump;
171 static void
172 error_context_errmsg_free(struct error_context *ec)
174 if (ec->errmsg != emergency.errmsg)
175 free(ec->errmsg);
176 ec->errmsg = NULL;
179 static void
180 error_context_errmsg_set(struct error_context *ec, char *errmsg)
182 error_context_errmsg_free(ec);
183 ec->errmsg = errmsg;
186 static int DPKG_ATTR_VPRINTF(1)
187 error_context_errmsg_format(const char *fmt, va_list args)
189 va_list args_copy;
190 char *errmsg = NULL;
191 int rc;
193 va_copy(args_copy, args);
194 rc = vasprintf(&errmsg, fmt, args_copy);
195 va_end(args_copy);
197 /* If the message was constructed successfully, at least we have some
198 * error message, which is better than nothing. */
199 if (rc >= 0)
200 error_context_errmsg_set(econtext, errmsg);
202 if (rc < 0) {
203 /* If there was any error, just use the emergency error message buffer,
204 * even if it ends up being truncated, at least we will have a big part
205 * of the problem. */
206 rc = vsnprintf(emergency.errmsg, sizeof(emergency.errmsg), fmt, args);
208 /* Return failure only if we get truncated. */
209 if (rc >= (int)sizeof(emergency.errmsg))
210 rc = -1;
212 error_context_errmsg_set(econtext, emergency.errmsg);
215 return rc;
218 void
219 push_error_context_func(error_handler_func *handler,
220 error_printer_func *printer,
221 const void *printer_data)
223 struct error_context *ec;
225 ec = error_context_new();
226 set_error_printer(ec, printer, printer_data);
227 set_func_handler(ec, handler);
228 onerr_abort = 0;
231 void
232 push_error_context_jump(jmp_buf *jumper,
233 error_printer_func *printer,
234 const void *printer_data)
236 struct error_context *ec;
238 ec = error_context_new();
239 set_error_printer(ec, printer, printer_data);
240 set_jump_handler(ec, jumper);
241 onerr_abort = 0;
244 void
245 push_error_context(void)
247 push_error_context_func(catch_fatal_error, print_fatal_error, NULL);
250 static void
251 print_cleanup_error(const char *emsg, const void *data)
253 print_abort_error(_("error while cleaning up"), emsg);
256 static void
257 run_cleanups(struct error_context *econ, int flagsetin)
259 static volatile int preventrecurse= 0;
260 struct cleanup_entry *volatile cep;
261 struct cleanup_entry *ncep;
262 struct error_context recurserr, *oldecontext;
263 jmp_buf recurse_jump;
264 volatile int i, flagset;
266 if (econ->printer.func)
267 econ->printer.func(econ->errmsg, econ->printer.data);
269 if (++preventrecurse > 3) {
270 onerr_abort++;
271 print_cleanup_error(_("too many nested errors during error recovery"), NULL);
272 flagset= 0;
273 } else {
274 flagset= flagsetin;
276 cep= econ->cleanups;
277 oldecontext= econtext;
278 while (cep) {
279 for (i=0; i<NCALLS; i++) {
280 if (cep->calls[i].call && cep->calls[i].mask & flagset) {
281 if (setjmp(recurse_jump)) {
282 run_cleanups(&recurserr, ehflag_bombout | ehflag_recursiveerror);
283 error_context_errmsg_free(&recurserr);
284 } else {
285 memset(&recurserr, 0, sizeof(recurserr));
286 set_error_printer(&recurserr, print_cleanup_error, NULL);
287 set_jump_handler(&recurserr, &recurse_jump);
288 econtext= &recurserr;
289 cep->calls[i].call(cep->argc,cep->argv);
291 econtext= oldecontext;
294 flagset &= cep->cpmask;
295 flagset |= cep->cpvalue;
296 ncep= cep->next;
297 if (cep != &emergency.ce) free(cep);
298 cep= ncep;
300 preventrecurse--;
304 * Push an error cleanup checkpoint.
306 * This will arrange that when pop_error_context() is called, all previous
307 * cleanups will be executed with
308 * flagset = (original_flagset & mask) | value
309 * where original_flagset is the argument to pop_error_context() (as
310 * modified by any checkpoint which was pushed later).
312 void push_checkpoint(int mask, int value) {
313 struct cleanup_entry *cep;
314 int i;
316 cep = malloc(sizeof(*cep) + sizeof(void *));
317 if (cep == NULL) {
318 onerr_abort++;
319 ohshite(_("out of memory for new cleanup entry"));
322 for (i=0; i<NCALLS; i++) { cep->calls[i].call=NULL; cep->calls[i].mask=0; }
323 cep->cpmask= mask; cep->cpvalue= value;
324 cep->argc= 0; cep->argv[0]= NULL;
325 cep->next= econtext->cleanups;
326 econtext->cleanups= cep;
329 static void
330 cleanup_entry_new(void (*call1)(int argc, void **argv), int mask1,
331 void (*call2)(int argc, void **argv), int mask2,
332 unsigned int nargs, va_list vargs)
334 struct cleanup_entry *cep;
335 void **argv;
336 int e = 0;
337 va_list args;
339 onerr_abort++;
341 cep = malloc(sizeof(*cep) + sizeof(void *) * (nargs + 1));
342 if (!cep) {
343 if (nargs > array_count(emergency.args))
344 ohshite(_("out of memory for new cleanup entry with many arguments"));
345 e= errno; cep= &emergency.ce;
347 cep->calls[0].call= call1; cep->calls[0].mask= mask1;
348 cep->calls[1].call= call2; cep->calls[1].mask= mask2;
349 cep->cpmask=~0; cep->cpvalue=0; cep->argc= nargs;
351 va_copy(args, vargs);
352 argv = cep->argv;
353 while (nargs-- > 0)
354 *argv++ = va_arg(args, void *);
355 *argv++ = NULL;
356 va_end(args);
357 cep->next= econtext->cleanups;
358 econtext->cleanups= cep;
359 if (cep == &emergency.ce) {
360 errno = e;
361 ohshite(_("out of memory for new cleanup entry"));
364 onerr_abort--;
367 void
368 push_cleanup(void (*call)(int argc, void **argv), int mask,
369 unsigned int nargs, ...)
371 va_list args;
373 va_start(args, nargs);
374 cleanup_entry_new(call, mask, NULL, 0, nargs, args);
375 va_end(args);
378 void
379 push_cleanup_fallback(void (*call1)(int argc, void **argv), int mask1,
380 void (*call2)(int argc, void **argv), int mask2,
381 unsigned int nargs, ...)
383 va_list args;
385 va_start(args, nargs);
386 cleanup_entry_new(call1, mask1, call2, mask2, nargs, args);
387 va_end(args);
390 void pop_cleanup(int flagset) {
391 struct cleanup_entry *cep;
392 int i;
394 cep= econtext->cleanups;
395 econtext->cleanups= cep->next;
396 for (i=0; i<NCALLS; i++) {
397 if (cep->calls[i].call && cep->calls[i].mask & flagset)
398 cep->calls[i].call(cep->argc,cep->argv);
400 if (cep != &emergency.ce) free(cep);
404 * Unwind the current error context by running its registered cleanups.
406 void
407 pop_error_context(int flagset)
409 struct error_context *tecp;
411 tecp = econtext;
412 econtext = tecp->next;
414 /* If we are cleaning up normally, do not print anything. */
415 if (flagset & ehflag_normaltidy)
416 set_error_printer(tecp, NULL, NULL);
417 run_cleanups(tecp, flagset);
419 error_context_errmsg_free(tecp);
420 free(tecp);
423 static void DPKG_ATTR_NORET
424 run_error_handler(void)
426 if (onerr_abort) {
427 /* We arrived here due to a fatal error from which we cannot recover,
428 * and trying to do so would most probably get us here again. That's
429 * why we will not try to do any error unwinding either. We'll just
430 * abort. Hopefully the user can fix the situation (out of disk, out
431 * of memory, etc). */
432 print_abort_error(_("unrecoverable fatal error, aborting"), econtext->errmsg);
433 error_context_errmsg_free(econtext);
434 exit(2);
437 if (econtext == NULL) {
438 print_abort_error(_("outside error context, aborting"),
439 _("an error occurred with no error handling in place"));
440 exit(2);
441 } else if (econtext->handler_type == HANDLER_TYPE_FUNC) {
442 econtext->handler.func();
443 internerr("error handler returned unexpectedly!");
444 } else if (econtext->handler_type == HANDLER_TYPE_JUMP) {
445 longjmp(*econtext->handler.jump, 1);
446 } else {
447 internerr("unknown error handler type %d!", econtext->handler_type);
451 void ohshit(const char *fmt, ...) {
452 va_list args;
454 va_start(args, fmt);
455 error_context_errmsg_format(fmt, args);
456 va_end(args);
458 run_error_handler();
461 void
462 ohshitv(const char *fmt, va_list args)
464 error_context_errmsg_format(fmt, args);
466 run_error_handler();
469 void ohshite(const char *fmt, ...) {
470 int e, rc;
471 va_list args;
473 e=errno;
475 /* First we construct the formatted message. */
476 va_start(args, fmt);
477 rc = error_context_errmsg_format(fmt, args);
478 va_end(args);
480 /* Then if there was no error we append the string for errno. Otherwise
481 * we just use the emergency error message buffer, and ignore the errno
482 * value, as we will probably have no space left anyway. */
483 if (rc > 0) {
484 char *errmsg = NULL;
486 rc = asprintf(&errmsg, "%s: %s", econtext->errmsg, strerror(e));
487 if (rc > 0)
488 error_context_errmsg_set(econtext, errmsg);
491 run_error_handler();
494 void
495 do_internerr(const char *file, int line, const char *func, const char *fmt, ...)
497 va_list args;
499 va_start(args, fmt);
500 error_context_errmsg_format(fmt, args);
501 va_end(args);
503 fprintf(stderr, "%s%s:%s:%d:%s:%s %s%s:%s %s\n", color_get(COLOR_PROG),
504 dpkg_get_progname(), file, line, func, color_reset(),
505 color_get(COLOR_ERROR), _("internal error"), color_reset(),
506 econtext->errmsg);
508 error_context_errmsg_free(econtext);
510 abort();