source: web/old/remctl-2.14/util/messages-die.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 4.4 KB
Line 
1/*
2 * Message and error reporting (fatal).
3 *
4 * Usage:
5 *
6 *     extern int cleanup(void);
7 *     extern void log(int, const char *, va_list, int);
8 *
9 *     message_fatal_cleanup = cleanup;
10 *     message_program_name = argv[0];
11 *
12 *     die("Something fatal happened at %lu", time);
13 *     sysdie("open of %s failed", filename);
14 *
15 *     message_handlers_die(1, log);
16 *     die("This now goes through our log function");
17 *
18 * die() implements message reporting through user-configurable handler
19 * functions and then exits, normally with a status of 1.  sysdie() does the
20 * same but appends a colon, a space, and the results of strerror(errno) to
21 * the end of the message.  Both functions accept printf-style formatting
22 * strings and arguments.
23 *
24 * If message_fatal_cleanup is non-NULL, it is called before exit by die and
25 * sysdie and its return value is used as the argument to exit.  It is a
26 * pointer to a function taking no arguments and returning an int, and can be
27 * used to call cleanup functions or to exit in some alternate fashion (such
28 * as by calling _exit).
29 *
30 * If message_program_name is non-NULL, the string it points to, followed by a
31 * colon and a space, is prepended to all error messages logged through the
32 * message_log_stderr message handler (the default for die).
33 *
34 * Honoring error_program_name and printing to stderr is just the default
35 * handler; with message_handlers_die the handler for die() can be changed.
36 * By default, die prints to stderr.  message_handlers_die takes a count of
37 * handlers and then that many function pointers, each one to a function that
38 * takes a message length (the number of characters snprintf generates given
39 * the format and arguments), a format, an argument list as a va_list, and the
40 * applicable errno value (if any).
41 *
42 * This file is separate from messages.c so that the potentially fatal
43 * functions aren't linked with code that will never call exit().  This helps
44 * automated analysis ensure that shared libraries don't call exit().
45 *
46 * Copyright 2009 Russ Allbery <rra@stanford.edu>
47 * Copyright 2008 Board of Trustees, Leland Stanford Jr. University
48 * Copyright (c) 2004, 2005, 2006
49 *     by Internet Systems Consortium, Inc. ("ISC")
50 * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
51 *     2002, 2003 by The Internet Software Consortium and Rich Salz
52 *
53 * See LICENSE for licensing terms.
54 */
55
56#include <config.h>
57#include <portable/system.h>
58
59#include <errno.h>
60
61#include <util/util.h>
62
63/* The default message handler. */
64static message_handler_func stderr_handlers[2] = {
65    message_log_stderr, NULL
66};
67static message_handler_func *die_handlers = stderr_handlers;
68
69/* If non-NULL, called before exit and its return value passed to exit. */
70int (*message_fatal_cleanup)(void) = NULL;
71
72
73/*
74 * Set the handlers for die.  This duplicates code from messages.c but seems
75 * to be the best way to handle separating the potentially fatal functions
76 * from the rest.
77 */
78void
79message_handlers_die(int count, ...)
80{
81    va_list args;
82    int i;
83
84    va_start(args, count);
85    if (die_handlers != stderr_handlers)
86        free(die_handlers);
87    die_handlers = xmalloc(sizeof(message_handler_func) * (count + 1));
88    for (i = 0; i < count; i++)
89        die_handlers[i] = va_arg(args, message_handler_func);
90    die_handlers[count] = NULL;
91    va_end(args);
92}
93
94
95/*
96 * The error reporting functions.  There is code duplication between the two
97 * functions that could be avoided with judicious use of va_copy(), but it's
98 * never seemed worth the effort.
99 */
100void
101die(const char *format, ...)
102{
103    va_list args;
104    message_handler_func *log;
105    int length;
106
107    va_start(args, format);
108    length = vsnprintf(NULL, 0, format, args);
109    va_end(args);
110    if (length >= 0)
111        for (log = die_handlers; *log != NULL; log++) {
112            va_start(args, format);
113            (**log)(length, format, args, 0);
114            va_end(args);
115        }
116    exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1);
117}
118
119void
120sysdie(const char *format, ...)
121{
122    va_list args;
123    message_handler_func *log;
124    int length;
125    int error = errno;
126
127    va_start(args, format);
128    length = vsnprintf(NULL, 0, format, args);
129    va_end(args);
130    if (length >= 0)
131        for (log = die_handlers; *log != NULL; log++) {
132            va_start(args, format);
133            (**log)(length, format, args, error);
134            va_end(args);
135        }
136    exit(message_fatal_cleanup ? (*message_fatal_cleanup)() : 1);
137}
Note: See TracBrowser for help on using the repository browser.