1 #ifndef FAILURES_H
2 #define FAILURES_H
3 
4 struct ip_addr;
5 
6 /* Default exit status codes that we could use. */
7 enum fatal_exit_status {
8 	FATAL_LOGOPEN	= 80, /* Can't open log file */
9 	FATAL_LOGWRITE  = 81, /* Can't write to log file */
10 	FATAL_LOGERROR  = 82, /* Internal logging error */
11 	FATAL_OUTOFMEM	= 83, /* Out of memory */
12 	FATAL_EXEC	= 84, /* exec() failed */
13 
14 	FATAL_DEFAULT	= 89
15 };
16 
17 enum log_type {
18 	LOG_TYPE_DEBUG,
19 	LOG_TYPE_INFO,
20 	LOG_TYPE_WARNING,
21 	LOG_TYPE_ERROR,
22 	LOG_TYPE_FATAL,
23 	LOG_TYPE_PANIC,
24 
25 	LOG_TYPE_COUNT,
26 	/* special case */
27 	LOG_TYPE_OPTION
28 };
29 
30 struct failure_line {
31 	pid_t pid;
32 	enum log_type log_type;
33 	/* If non-zero, the first log_prefix_len bytes in text indicate
34 	   the log prefix. This implies disable_log_prefix=TRUE. */
35 	unsigned int log_prefix_len;
36 	/* Disable the global log prefix. */
37 	bool disable_log_prefix;
38 	const char *text;
39 };
40 
41 struct failure_context {
42 	enum log_type type;
43 	int exit_status; /* for LOG_TYPE_FATAL */
44 	const struct tm *timestamp; /* NULL = use time() + localtime() */
45 	unsigned int timestamp_usecs;
46 	const char *log_prefix; /* override the default log prefix */
47 	/* If non-0, insert the log type text (e.g. "Info: ") at this position
48 	   in the log_prefix instead of appending it. */
49 	unsigned int log_prefix_type_pos;
50 };
51 
52 #define DEFAULT_FAILURE_STAMP_FORMAT "%b %d %H:%M:%S "
53 
54 typedef void failure_callback_t(const struct failure_context *ctx,
55 				const char *format, va_list args);
56 
57 extern const char *failure_log_type_prefixes[];
58 extern const char *failure_log_type_names[];
59 
60 void i_log_type(const struct failure_context *ctx, const char *format, ...)
61 	ATTR_FORMAT(2, 3);
62 void i_log_typev(const struct failure_context *ctx, const char *format,
63 		 va_list args) ATTR_FORMAT(2, 0);
64 
65 void i_panic(const char *format, ...) ATTR_FORMAT(1, 2) ATTR_NORETURN ATTR_COLD;
66 void i_fatal(const char *format, ...) ATTR_FORMAT(1, 2) ATTR_NORETURN ATTR_COLD;
67 void i_error(const char *format, ...) ATTR_FORMAT(1, 2) ATTR_COLD;
68 void i_warning(const char *format, ...) ATTR_FORMAT(1, 2);
69 void i_info(const char *format, ...) ATTR_FORMAT(1, 2);
70 void i_debug(const char *format, ...) ATTR_FORMAT(1, 2);
71 
72 void i_fatal_status(int status, const char *format, ...)
73 	ATTR_FORMAT(2, 3) ATTR_NORETURN ATTR_COLD;
74 
75 /* Change failure handlers. */
76 #ifndef __cplusplus
77 void i_set_fatal_handler(failure_callback_t *callback ATTR_NORETURN);
78 #else
79 /* Older g++ doesn't like attributes in parameters */
80 void i_set_fatal_handler(failure_callback_t *callback);
81 #endif
82 void i_set_error_handler(failure_callback_t *callback);
83 void i_set_info_handler(failure_callback_t *callback);
84 void i_set_debug_handler(failure_callback_t *callback);
85 void i_get_failure_handlers(failure_callback_t **fatal_callback_r,
86 			    failure_callback_t **error_callback_r,
87 			    failure_callback_t **info_callback_r,
88 			    failure_callback_t **debug_callback_r);
89 
90 /* Send failures to file. */
91 void default_fatal_handler(const struct failure_context *ctx,
92 			   const char *format, va_list args)
93 	ATTR_NORETURN ATTR_FORMAT(2, 0);
94 void default_error_handler(const struct failure_context *ctx,
95 			   const char *format, va_list args)
96 	ATTR_FORMAT(2, 0);
97 
98 /* Send failures to syslog() */
99 void i_syslog_fatal_handler(const struct failure_context *ctx,
100 			    const char *format, va_list args)
101 	ATTR_NORETURN ATTR_FORMAT(2, 0);
102 void i_syslog_error_handler(const struct failure_context *ctx,
103 			    const char *format, va_list args)
104 	ATTR_FORMAT(2, 0);
105 
106 /* Open syslog and set failure/info/debug handlers to use it. */
107 void i_set_failure_syslog(const char *ident, int options, int facility);
108 
109 /* Send failures to specified log file instead of stderr. */
110 void i_set_failure_file(const char *path, const char *prefix);
111 
112 /* Send errors to stderr using internal error protocol. */
113 void i_set_failure_internal(void);
114 /* Returns TRUE if the given callback handler was set via
115    i_set_failure_internal(). */
116 bool i_failure_handler_is_internal(failure_callback_t *const callback);
117 /* If writing to log fails, ignore it instead of existing with
118    FATAL_LOGWRITE or FATAL_LOGERROR. */
119 void i_set_failure_ignore_errors(bool ignore);
120 
121 /* Send informational messages to specified log file. i_set_failure_*()
122    functions modify the info file too, so call this function after them. */
123 void i_set_info_file(const char *path);
124 
125 /* Send debug-level message to the given log file. The i_set_info_file()
126    function modifies also the debug log file, so call this function after it. */
127 void i_set_debug_file(const char *path);
128 
129 /* Set the failure prefix. */
130 void i_set_failure_prefix(const char *prefix_fmt, ...) ATTR_FORMAT(1, 2);
131 /* Set prefix to "". */
132 void i_unset_failure_prefix(void);
133 /* Returns the current failure prefix (never NULL). */
134 const char *i_get_failure_prefix(void);
135 /* Prefix failures with a timestamp. fmt is in strftime() format. */
136 void i_set_failure_timestamp_format(const char *fmt);
137 /* When logging with internal error protocol, update the process's current
138    IP address / log prefix by sending it to log process. This is mainly used to
139    improve the error message if the process crashes. */
140 void i_set_failure_send_ip(const struct ip_addr *ip);
141 void i_set_failure_send_prefix(const char *prefix);
142 
143 /* Call the callback before exit()ing. The callback may update the status. */
144 void i_set_failure_exit_callback(void (*callback)(int *status));
145 /* Call the exit callback and exit() */
146 void failure_exit(int status) ATTR_NORETURN ATTR_COLD;
147 
148 /* Parse a line logged using internal failure handler */
149 void i_failure_parse_line(const char *line, struct failure_line *failure);
150 
151 void failures_deinit(void);
152 
153 #endif
154