1/*
2 * Copyright (c) 1997 - 2001 Kungliga Tekniska H��gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "krb5_locl.h"
35#include <err.h>
36
37static krb5_error_code _warnerr(krb5_context context, int do_errtext,
38	 krb5_error_code code, int level, const char *fmt, va_list ap)
39	__attribute__((__format__(__printf__, 5, 0)));
40
41static krb5_error_code
42_warnerr(krb5_context context, int do_errtext,
43	 krb5_error_code code, int level, const char *fmt, va_list ap)
44{
45    char xfmt[7] = "";
46    const char *args[2], **arg;
47    char *msg = NULL;
48    const char *err_str = NULL;
49    krb5_error_code ret;
50
51    args[0] = args[1] = NULL;
52    arg = args;
53    if(fmt){
54	strlcat(xfmt, "%s", sizeof(xfmt));
55	if(do_errtext)
56	    strlcat(xfmt, ": ", sizeof(xfmt));
57	ret = vasprintf(&msg, fmt, ap);
58	if(ret < 0 || msg == NULL)
59	    return ENOMEM;
60	*arg++ = msg;
61    }
62    if(context && do_errtext){
63	strlcat(xfmt, "%s", sizeof(xfmt));
64
65	err_str = krb5_get_error_message(context, code);
66	if (err_str != NULL) {
67	    *arg = err_str;
68	} else {
69	    *arg= "<unknown error>";
70	}
71    }
72
73    if(context && context->warn_dest)
74	krb5_log(context, context->warn_dest, level, xfmt, args[0], args[1]);
75    else
76	warnx(xfmt, args[0], args[1]);
77    free(msg);
78    krb5_free_error_message(context, err_str);
79    return 0;
80}
81
82#define FUNC(ETEXT, CODE, LEVEL)					\
83    krb5_error_code ret;						\
84    va_list ap;								\
85    va_start(ap, fmt);							\
86    ret = _warnerr(context, ETEXT, CODE, LEVEL, fmt, ap); 		\
87    va_end(ap);
88
89#undef __attribute__
90#define __attribute__(X)
91
92/**
93 * Log a warning to the log, default stderr, include the error from
94 * the last failure.
95 *
96 * @param context A Kerberos 5 context.
97 * @param code error code of the last error
98 * @param fmt message to print
99 * @param ap arguments
100 *
101 * @ingroup krb5_error
102 */
103
104KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
105krb5_vwarn(krb5_context context, krb5_error_code code,
106	   const char *fmt, va_list ap)
107     __attribute__ ((format (printf, 3, 0)))
108{
109    return _warnerr(context, 1, code, 1, fmt, ap);
110}
111
112/**
113 * Log a warning to the log, default stderr, include the error from
114 * the last failure.
115 *
116 * @param context A Kerberos 5 context.
117 * @param code error code of the last error
118 * @param fmt message to print
119 *
120 * @ingroup krb5_error
121 */
122
123KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
124krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...)
125     __attribute__ ((format (printf, 3, 4)))
126{
127    FUNC(1, code, 1);
128    return ret;
129}
130
131/**
132 * Log a warning to the log, default stderr.
133 *
134 * @param context A Kerberos 5 context.
135 * @param fmt message to print
136 * @param ap arguments
137 *
138 * @ingroup krb5_error
139 */
140
141KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
142krb5_vwarnx(krb5_context context, const char *fmt, va_list ap)
143     __attribute__ ((format (printf, 2, 0)))
144{
145    return _warnerr(context, 0, 0, 1, fmt, ap);
146}
147
148/**
149 * Log a warning to the log, default stderr.
150 *
151 * @param context A Kerberos 5 context.
152 * @param fmt message to print
153 *
154 * @ingroup krb5_error
155 */
156
157KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
158krb5_warnx(krb5_context context, const char *fmt, ...)
159     __attribute__ ((format (printf, 2, 3)))
160{
161    FUNC(0, 0, 1);
162    return ret;
163}
164
165/**
166 * Log a warning to the log, default stderr, include bthe error from
167 * the last failure and then exit.
168 *
169 * @param context A Kerberos 5 context
170 * @param eval the exit code to exit with
171 * @param code error code of the last error
172 * @param fmt message to print
173 * @param ap arguments
174 *
175 * @ingroup krb5_error
176 */
177
178KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
179krb5_verr(krb5_context context, int eval, krb5_error_code code,
180	  const char *fmt, va_list ap)
181     __attribute__ ((noreturn, format (printf, 4, 0)))
182{
183    _warnerr(context, 1, code, 0, fmt, ap);
184    exit(eval);
185    UNREACHABLE(return 0);
186}
187
188/**
189 * Log a warning to the log, default stderr, include bthe error from
190 * the last failure and then exit.
191 *
192 * @param context A Kerberos 5 context
193 * @param eval the exit code to exit with
194 * @param code error code of the last error
195 * @param fmt message to print
196 *
197 * @ingroup krb5_error
198 */
199
200KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
201krb5_err(krb5_context context, int eval, krb5_error_code code,
202	 const char *fmt, ...)
203     __attribute__ ((noreturn, format (printf, 4, 5)))
204{
205    FUNC(1, code, 0);
206    exit(eval);
207    UNREACHABLE(return 0);
208}
209
210/**
211 * Log a warning to the log, default stderr, and then exit.
212 *
213 * @param context A Kerberos 5 context
214 * @param eval the exit code to exit with
215 * @param fmt message to print
216 * @param ap arguments
217 *
218 * @ingroup krb5_error
219 */
220
221KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
222krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap)
223     __attribute__ ((noreturn, format (printf, 3, 0)))
224{
225    _warnerr(context, 0, 0, 0, fmt, ap);
226    exit(eval);
227    UNREACHABLE(return 0);
228}
229
230/**
231 * Log a warning to the log, default stderr, and then exit.
232 *
233 * @param context A Kerberos 5 context
234 * @param eval the exit code to exit with
235 * @param fmt message to print
236 *
237 * @ingroup krb5_error
238 */
239
240KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
241krb5_errx(krb5_context context, int eval, const char *fmt, ...)
242     __attribute__ ((noreturn, format (printf, 3, 4)))
243{
244    FUNC(0, 0, 0);
245    exit(eval);
246    UNREACHABLE(return 0);
247}
248
249/**
250 * Log a warning to the log, default stderr, include bthe error from
251 * the last failure and then abort.
252 *
253 * @param context A Kerberos 5 context
254 * @param code error code of the last error
255 * @param fmt message to print
256 * @param ap arguments
257 *
258 * @ingroup krb5_error
259 */
260
261KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
262krb5_vabort(krb5_context context, krb5_error_code code,
263	    const char *fmt, va_list ap)
264     __attribute__ ((noreturn, format (printf, 3, 0)))
265{
266    _warnerr(context, 1, code, 0, fmt, ap);
267    abort();
268    UNREACHABLE(return 0);
269}
270
271/**
272 * Log a warning to the log, default stderr, include the error from
273 * the last failure and then abort.
274 *
275 * @param context A Kerberos 5 context
276 * @param code error code of the last error
277 * @param fmt message to print
278 *
279 * @ingroup krb5_error
280 */
281
282KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
283krb5_abort(krb5_context context, krb5_error_code code, const char *fmt, ...)
284     __attribute__ ((noreturn, format (printf, 3, 4)))
285{
286    FUNC(1, code, 0);
287    abort();
288    UNREACHABLE(return 0);
289}
290
291KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
292krb5_vabortx(krb5_context context, const char *fmt, va_list ap)
293     __attribute__ ((noreturn, format (printf, 2, 0)))
294{
295    _warnerr(context, 0, 0, 0, fmt, ap);
296    abort();
297    UNREACHABLE(return 0);
298}
299
300/**
301 * Log a warning to the log, default stderr, and then abort.
302 *
303 * @param context A Kerberos 5 context
304 * @param code error code of the last error
305 * @param fmt message to print
306 *
307 * @ingroup krb5_error
308 */
309
310KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
311krb5_abortx(krb5_context context, const char *fmt, ...)
312     __attribute__ ((noreturn, format (printf, 2, 3)))
313{
314    FUNC(0, 0, 0);
315    abort();
316    UNREACHABLE(return 0);
317}
318
319/**
320 * Set the default logging facility.
321 *
322 * @param context A Kerberos 5 context
323 * @param fac Facility to use for logging.
324 *
325 * @ingroup krb5_error
326 */
327
328KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
329krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac)
330{
331    context->warn_dest = fac;
332    return 0;
333}
334
335/**
336 * Get the default logging facility.
337 *
338 * @param context A Kerberos 5 context
339 *
340 * @ingroup krb5_error
341 */
342
343KRB5_LIB_FUNCTION krb5_log_facility * KRB5_LIB_CALL
344krb5_get_warn_dest(krb5_context context)
345{
346    return context->warn_dest;
347}
348