1 /*
2  * SPDX-License-Identifier: ISC
3  *
4  * Copyright (c) 2004, 2010-2015, 2017-2018 Todd C. Miller <Todd.Miller@sudo.ws>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef SUDO_FATAL_H
20 #define	SUDO_FATAL_H
21 
22 #include <stdarg.h>
23 #ifdef HAVE_STDBOOL_H
24 # include <stdbool.h>
25 #else
26 # include "compat/stdbool.h"
27 #endif /* HAVE_STDBOOL_H */
28 
29 #include "sudo_plugin.h"	/* for conversation function */
30 
31 /*
32  * We wrap fatal/fatalx and warn/warnx so that the same output can
33  * go to the debug file, if there is one.
34  */
35 #if (defined(SUDO_ERROR_WRAP) && SUDO_ERROR_WRAP == 0) || defined(NO_VARIADIC_MACROS)
36 # define sudo_fatal sudo_fatal_nodebug_v1
37 # define sudo_fatalx sudo_fatalx_nodebug_v1
38 # define sudo_gai_fatal sudo_gai_fatal_nodebug_v1
39 # define sudo_warn sudo_warn_nodebug_v1
40 # define sudo_warnx sudo_warnx_nodebug_v1
41 # define sudo_gai_warn sudo_gai_warn_nodebug_v1
42 # define sudo_vfatal(fmt, ap) sudo_vfatal_nodebug_v1((fmt), (ap))
43 # define sudo_vfatalx(fmt, ap) sudo_vfatalx_nodebug_v1((fmt), (ap))
44 # define sudo_gai_vfatal(en, fmt, ap) sudo_vfatal_nodebug_v1((en), (fmt), (ap))
45 # define sudo_vwarn(fmt, ap) sudo_vwarn_nodebug_v1((fmt), (ap))
46 # define sudo_vwarnx(fmt, ap) sudo_vwarnx_nodebug_v1((fmt), (ap))
47 # define sudo_gai_vwarn(en, fmt, ap) sudo_vwarn_nodebug_v1((en), (fmt), (ap))
48 #else /* SUDO_ERROR_WRAP */
49 # if defined(__GNUC__) && __GNUC__ == 2
50 #  define sudo_fatal(fmt...) do {					       \
51     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
52 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
53 	fmt);								       \
54     sudo_fatal_nodebug_v1(fmt);						       \
55 } while (0)
56 #  define sudo_fatalx(fmt...) do {					       \
57     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
58 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, fmt);	       \
59     sudo_fatalx_nodebug_v1(fmt);					       \
60 } while (0)
61 #  define sudo_gai_fatal(en, fmt...) do {				       \
62     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
63 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, fmt);	       \
64     sudo_gai_fatal_nodebug_v1((en), fmt);				       \
65 } while (0)
66 #  define sudo_warn(fmt...) do {					       \
67     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
68 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
69 	fmt);								       \
70     sudo_warn_nodebug_v1(fmt);						       \
71 } while (0)
72 #  define sudo_warnx(fmt...) do {					       \
73     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
74 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, fmt);	       \
75     sudo_warnx_nodebug_v1(fmt);						       \
76 } while (0)
77 #  define sudo_gai_warn(en, fmt...) do {				       \
78     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
79 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, fmt);	       \
80     sudo_gai_warn_nodebug_v1((en), fmt);				       \
81 } while (0)
82 # else
83 #  define sudo_fatal(...) do {						       \
84     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
85 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
86 	__VA_ARGS__);							       \
87     sudo_fatal_nodebug_v1(__VA_ARGS__);					       \
88 } while (0)
89 #  define sudo_fatalx(...) do {						       \
90     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
91 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, __VA_ARGS__);    \
92     sudo_fatalx_nodebug_v1(__VA_ARGS__);				       \
93 } while (0)
94 #  define sudo_gai_fatal(en, ...) do {					       \
95     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
96 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, __VA_ARGS__);    \
97     sudo_gai_fatal_nodebug_v1((en), __VA_ARGS__);			       \
98 } while (0)
99 #  define sudo_warn(...) do {						       \
100     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
101 	SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys,  \
102 	__VA_ARGS__);							       \
103     sudo_warn_nodebug_v1(__VA_ARGS__);					       \
104 } while (0)
105 #  define sudo_warnx(...) do {						       \
106     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
107 	SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|sudo_debug_subsys, __VA_ARGS__);     \
108     sudo_warnx_nodebug_v1(__VA_ARGS__);					       \
109 } while (0)
110 #  define sudo_gai_warn(en, ...) do {					       \
111     sudo_debug_printf2(__func__, __FILE__, __LINE__,			       \
112 	SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|sudo_debug_subsys, __VA_ARGS__);     \
113     sudo_gai_warn_nodebug_v1((en), __VA_ARGS__);			       \
114 } while (0)
115 # endif /* __GNUC__ == 2 */
116 # define sudo_vfatal(fmt, ap) do {					       \
117     va_list ap2;							       \
118     va_copy(ap2, (ap));							       \
119     sudo_debug_vprintf2(__func__, __FILE__, __LINE__,			       \
120 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
121 	(fmt), ap2);							       \
122     sudo_vfatal_nodebug_v1((fmt), (ap));					       \
123 } while (0)
124 # define sudo_vfatalx(fmt, ap) do {					       \
125     va_list ap2;							       \
126     va_copy(ap2, (ap));							       \
127     sudo_debug_vprintf2(__func__, __FILE__, __LINE__,			       \
128 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, (fmt), ap2);     \
129     sudo_vfatalx_nodebug_v1((fmt), (ap));				       \
130 } while (0)
131 # define sudo_gai_vfatal(en, fmt, ap) do {				       \
132     va_list ap2;							       \
133     va_copy(ap2, (ap));							       \
134     sudo_debug_vprintf2(__func__, __FILE__, __LINE__,			       \
135 	SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, (fmt), ap2);     \
136     sudo_gai_vfatal_nodebug_v1((en), (fmt), (ap));			       \
137 } while (0)
138 # define sudo_vwarn(fmt, ap) do {					       \
139     va_list ap2;							       \
140     va_copy(ap2, (ap));							       \
141     sudo_debug_vprintf2(__func__, __FILE__, __LINE__,			       \
142 	SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys,  \
143 	(fmt), ap2);							       \
144     sudo_vwarn_nodebug_v1((fmt), (ap));					       \
145 } while (0)
146 # define sudo_vwarnx(fmt, ap) do {					       \
147     va_list ap2;							       \
148     va_copy(ap2, (ap));							       \
149     sudo_debug_vprintf2(__func__, __FILE__, __LINE__,			       \
150 	SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|sudo_debug_subsys, (fmt), ap2);      \
151     sudo_vwarnx_nodebug_v1((fmt), (ap));				       \
152 } while (0)
153 # define sudo_gai_vwarn(en, fmt, ap) do {				       \
154     va_list ap2;							       \
155     va_copy(ap2, (ap));							       \
156     sudo_debug_vprintf2(__func__, __FILE__, __LINE__,			       \
157 	SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|sudo_debug_subsys, (fmt), ap2);      \
158     sudo_gai_vwarn_nodebug_v1((en), (fmt), (ap));			       \
159 } while (0)
160 #endif /* SUDO_ERROR_WRAP */
161 
162 typedef void (*sudo_fatal_callback_t)(void);
163 typedef bool (*sudo_warn_setlocale_t)(bool, int *);
164 
165 sudo_dso_public int  sudo_fatal_callback_deregister_v1(sudo_fatal_callback_t func);
166 sudo_dso_public int  sudo_fatal_callback_register_v1(sudo_fatal_callback_t func);
167 sudo_dso_public char *sudo_warn_gettext_v1(const char *domainname, const char *msgid) __format_arg(2);
168 sudo_dso_public void sudo_warn_set_locale_func_v1(sudo_warn_setlocale_t func);
169 sudo_dso_public void sudo_fatal_nodebug_v1(const char *fmt, ...) __printf0like(1, 2) __attribute__((__noreturn__));
170 sudo_dso_public void sudo_fatalx_nodebug_v1(const char *fmt, ...) __printflike(1, 2) __attribute__((__noreturn__));
171 sudo_dso_public void sudo_gai_fatal_nodebug_v1(int errnum, const char *fmt, ...) __printflike(2, 3) __attribute__((__noreturn__));
172 sudo_dso_public void sudo_vfatal_nodebug_v1(const char *fmt, va_list ap) __printf0like(1, 0) __attribute__((__noreturn__));
173 sudo_dso_public void sudo_vfatalx_nodebug_v1(const char *fmt, va_list ap) __printflike(1, 0) __attribute__((__noreturn__));
174 sudo_dso_public void sudo_gai_vfatal_nodebug_v1(int errnum, const char *fmt, va_list ap) __printflike(2, 0) __attribute__((__noreturn__));
175 sudo_dso_public void sudo_warn_nodebug_v1(const char *fmt, ...) __printf0like(1, 2);
176 sudo_dso_public void sudo_warnx_nodebug_v1(const char *fmt, ...) __printflike(1, 2);
177 sudo_dso_public void sudo_gai_warn_nodebug_v1(int errnum, const char *fmt, ...) __printflike(2, 3);
178 sudo_dso_public void sudo_vwarn_nodebug_v1(const char *fmt, va_list ap) __printf0like(1, 0);
179 sudo_dso_public void sudo_vwarnx_nodebug_v1(const char *fmt, va_list ap) __printflike(1, 0);
180 sudo_dso_public void sudo_gai_vwarn_nodebug_v1(int errnum, const char *fmt, va_list ap) __printflike(2, 0);
181 sudo_dso_public void sudo_warn_set_conversation_v1(sudo_conv_t conv);
182 
183 #define sudo_fatal_callback_deregister(_a) sudo_fatal_callback_deregister_v1((_a))
184 #define sudo_fatal_callback_register(_a) sudo_fatal_callback_register_v1((_a))
185 #define sudo_warn_set_locale_func(_a) sudo_warn_set_locale_func_v1((_a))
186 #define sudo_fatal_nodebug sudo_fatal_nodebug_v1
187 #define sudo_fatalx_nodebug sudo_fatalx_nodebug_v1
188 #define sudo_gai_fatal_nodebug sudo_gai_fatal_nodebug_v1
189 #define sudo_vfatal_nodebug(_a, _b) sudo_vfatal_nodebug_v1((_a), (_b))
190 #define sudo_vfatalx_nodebug(_a, _b) sudo_vfatalx_nodebug_v1((_a), (_b))
191 #define sudo_gai_vfatal_nodebug(_a, _b, _c) sudo_gai_vfatal_nodebug_v1((_a), (_b), (_c))
192 #define sudo_warn_nodebug sudo_warn_nodebug_v1
193 #define sudo_warnx_nodebug sudo_warnx_nodebug_v1
194 #define sudo_gai_warn_nodebug sudo_gai_warn_nodebug_v1
195 #define sudo_vwarn_nodebug(_a, _b) sudo_vwarn_nodebug_v1((_a), (_b))
196 #define sudo_vwarnx_nodebug(_a, _b) sudo_vwarnx_nodebug_v1((_a), (_b))
197 #define sudo_gai_vwarn_nodebug(_a, _b, _c) sudo_gai_vwarn_nodebug_v1((_a), (_b), (_c))
198 #define sudo_warn_set_conversation(_a) sudo_warn_set_conversation_v1(_a)
199 
200 #ifdef DEFAULT_TEXT_DOMAIN
201 # define sudo_warn_gettext(_a) sudo_warn_gettext_v1(DEFAULT_TEXT_DOMAIN, (_a))
202 #else
203 # define sudo_warn_gettext(_a) sudo_warn_gettext_v1(NULL, (_a))
204 #endif
205 
206 #endif /* SUDO_FATAL_H */
207