1*ebfedea0SLionel Sambuc /* $NetBSD: error.c,v 1.1.1.1 2011/04/13 18:15:10 elric Exp $ */
2*ebfedea0SLionel Sambuc
3*ebfedea0SLionel Sambuc /*
4*ebfedea0SLionel Sambuc * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
5*ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden).
6*ebfedea0SLionel Sambuc * All rights reserved.
7*ebfedea0SLionel Sambuc *
8*ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9*ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10*ebfedea0SLionel Sambuc * are met:
11*ebfedea0SLionel Sambuc *
12*ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
13*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
14*ebfedea0SLionel Sambuc *
15*ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17*ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
18*ebfedea0SLionel Sambuc *
19*ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors
20*ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software
21*ebfedea0SLionel Sambuc * without specific prior written permission.
22*ebfedea0SLionel Sambuc *
23*ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24*ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27*ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*ebfedea0SLionel Sambuc * SUCH DAMAGE.
34*ebfedea0SLionel Sambuc */
35*ebfedea0SLionel Sambuc
36*ebfedea0SLionel Sambuc #include "hx_locl.h"
37*ebfedea0SLionel Sambuc
38*ebfedea0SLionel Sambuc /**
39*ebfedea0SLionel Sambuc * @page page_error Hx509 error reporting functions
40*ebfedea0SLionel Sambuc *
41*ebfedea0SLionel Sambuc * See the library functions here: @ref hx509_error
42*ebfedea0SLionel Sambuc */
43*ebfedea0SLionel Sambuc
44*ebfedea0SLionel Sambuc struct hx509_error_data {
45*ebfedea0SLionel Sambuc hx509_error next;
46*ebfedea0SLionel Sambuc int code;
47*ebfedea0SLionel Sambuc char *msg;
48*ebfedea0SLionel Sambuc };
49*ebfedea0SLionel Sambuc
50*ebfedea0SLionel Sambuc static void
free_error_string(hx509_error msg)51*ebfedea0SLionel Sambuc free_error_string(hx509_error msg)
52*ebfedea0SLionel Sambuc {
53*ebfedea0SLionel Sambuc while(msg) {
54*ebfedea0SLionel Sambuc hx509_error m2 = msg->next;
55*ebfedea0SLionel Sambuc free(msg->msg);
56*ebfedea0SLionel Sambuc free(msg);
57*ebfedea0SLionel Sambuc msg = m2;
58*ebfedea0SLionel Sambuc }
59*ebfedea0SLionel Sambuc }
60*ebfedea0SLionel Sambuc
61*ebfedea0SLionel Sambuc /**
62*ebfedea0SLionel Sambuc * Resets the error strings the hx509 context.
63*ebfedea0SLionel Sambuc *
64*ebfedea0SLionel Sambuc * @param context A hx509 context.
65*ebfedea0SLionel Sambuc *
66*ebfedea0SLionel Sambuc * @ingroup hx509_error
67*ebfedea0SLionel Sambuc */
68*ebfedea0SLionel Sambuc
69*ebfedea0SLionel Sambuc void
hx509_clear_error_string(hx509_context context)70*ebfedea0SLionel Sambuc hx509_clear_error_string(hx509_context context)
71*ebfedea0SLionel Sambuc {
72*ebfedea0SLionel Sambuc if (context) {
73*ebfedea0SLionel Sambuc free_error_string(context->error);
74*ebfedea0SLionel Sambuc context->error = NULL;
75*ebfedea0SLionel Sambuc }
76*ebfedea0SLionel Sambuc }
77*ebfedea0SLionel Sambuc
78*ebfedea0SLionel Sambuc /**
79*ebfedea0SLionel Sambuc * Add an error message to the hx509 context.
80*ebfedea0SLionel Sambuc *
81*ebfedea0SLionel Sambuc * @param context A hx509 context.
82*ebfedea0SLionel Sambuc * @param flags
83*ebfedea0SLionel Sambuc * - HX509_ERROR_APPEND appends the error string to the old messages
84*ebfedea0SLionel Sambuc (code is updated).
85*ebfedea0SLionel Sambuc * @param code error code related to error message
86*ebfedea0SLionel Sambuc * @param fmt error message format
87*ebfedea0SLionel Sambuc * @param ap arguments to error message format
88*ebfedea0SLionel Sambuc *
89*ebfedea0SLionel Sambuc * @ingroup hx509_error
90*ebfedea0SLionel Sambuc */
91*ebfedea0SLionel Sambuc
92*ebfedea0SLionel Sambuc void
hx509_set_error_stringv(hx509_context context,int flags,int code,const char * fmt,va_list ap)93*ebfedea0SLionel Sambuc hx509_set_error_stringv(hx509_context context, int flags, int code,
94*ebfedea0SLionel Sambuc const char *fmt, va_list ap)
95*ebfedea0SLionel Sambuc {
96*ebfedea0SLionel Sambuc hx509_error msg;
97*ebfedea0SLionel Sambuc
98*ebfedea0SLionel Sambuc if (context == NULL)
99*ebfedea0SLionel Sambuc return;
100*ebfedea0SLionel Sambuc
101*ebfedea0SLionel Sambuc msg = calloc(1, sizeof(*msg));
102*ebfedea0SLionel Sambuc if (msg == NULL) {
103*ebfedea0SLionel Sambuc hx509_clear_error_string(context);
104*ebfedea0SLionel Sambuc return;
105*ebfedea0SLionel Sambuc }
106*ebfedea0SLionel Sambuc
107*ebfedea0SLionel Sambuc if (vasprintf(&msg->msg, fmt, ap) == -1) {
108*ebfedea0SLionel Sambuc hx509_clear_error_string(context);
109*ebfedea0SLionel Sambuc free(msg);
110*ebfedea0SLionel Sambuc return;
111*ebfedea0SLionel Sambuc }
112*ebfedea0SLionel Sambuc msg->code = code;
113*ebfedea0SLionel Sambuc
114*ebfedea0SLionel Sambuc if (flags & HX509_ERROR_APPEND) {
115*ebfedea0SLionel Sambuc msg->next = context->error;
116*ebfedea0SLionel Sambuc context->error = msg;
117*ebfedea0SLionel Sambuc } else {
118*ebfedea0SLionel Sambuc free_error_string(context->error);
119*ebfedea0SLionel Sambuc context->error = msg;
120*ebfedea0SLionel Sambuc }
121*ebfedea0SLionel Sambuc }
122*ebfedea0SLionel Sambuc
123*ebfedea0SLionel Sambuc /**
124*ebfedea0SLionel Sambuc * See hx509_set_error_stringv().
125*ebfedea0SLionel Sambuc *
126*ebfedea0SLionel Sambuc * @param context A hx509 context.
127*ebfedea0SLionel Sambuc * @param flags
128*ebfedea0SLionel Sambuc * - HX509_ERROR_APPEND appends the error string to the old messages
129*ebfedea0SLionel Sambuc (code is updated).
130*ebfedea0SLionel Sambuc * @param code error code related to error message
131*ebfedea0SLionel Sambuc * @param fmt error message format
132*ebfedea0SLionel Sambuc * @param ... arguments to error message format
133*ebfedea0SLionel Sambuc *
134*ebfedea0SLionel Sambuc * @ingroup hx509_error
135*ebfedea0SLionel Sambuc */
136*ebfedea0SLionel Sambuc
137*ebfedea0SLionel Sambuc void
hx509_set_error_string(hx509_context context,int flags,int code,const char * fmt,...)138*ebfedea0SLionel Sambuc hx509_set_error_string(hx509_context context, int flags, int code,
139*ebfedea0SLionel Sambuc const char *fmt, ...)
140*ebfedea0SLionel Sambuc {
141*ebfedea0SLionel Sambuc va_list ap;
142*ebfedea0SLionel Sambuc
143*ebfedea0SLionel Sambuc va_start(ap, fmt);
144*ebfedea0SLionel Sambuc hx509_set_error_stringv(context, flags, code, fmt, ap);
145*ebfedea0SLionel Sambuc va_end(ap);
146*ebfedea0SLionel Sambuc }
147*ebfedea0SLionel Sambuc
148*ebfedea0SLionel Sambuc /**
149*ebfedea0SLionel Sambuc * Get an error string from context associated with error_code.
150*ebfedea0SLionel Sambuc *
151*ebfedea0SLionel Sambuc * @param context A hx509 context.
152*ebfedea0SLionel Sambuc * @param error_code Get error message for this error code.
153*ebfedea0SLionel Sambuc *
154*ebfedea0SLionel Sambuc * @return error string, free with hx509_free_error_string().
155*ebfedea0SLionel Sambuc *
156*ebfedea0SLionel Sambuc * @ingroup hx509_error
157*ebfedea0SLionel Sambuc */
158*ebfedea0SLionel Sambuc
159*ebfedea0SLionel Sambuc char *
hx509_get_error_string(hx509_context context,int error_code)160*ebfedea0SLionel Sambuc hx509_get_error_string(hx509_context context, int error_code)
161*ebfedea0SLionel Sambuc {
162*ebfedea0SLionel Sambuc struct rk_strpool *p = NULL;
163*ebfedea0SLionel Sambuc hx509_error msg = context->error;
164*ebfedea0SLionel Sambuc
165*ebfedea0SLionel Sambuc if (msg == NULL || msg->code != error_code) {
166*ebfedea0SLionel Sambuc const char *cstr;
167*ebfedea0SLionel Sambuc char *str;
168*ebfedea0SLionel Sambuc
169*ebfedea0SLionel Sambuc cstr = com_right(context->et_list, error_code);
170*ebfedea0SLionel Sambuc if (cstr)
171*ebfedea0SLionel Sambuc return strdup(cstr);
172*ebfedea0SLionel Sambuc cstr = strerror(error_code);
173*ebfedea0SLionel Sambuc if (cstr)
174*ebfedea0SLionel Sambuc return strdup(cstr);
175*ebfedea0SLionel Sambuc if (asprintf(&str, "<unknown error: %d>", error_code) == -1)
176*ebfedea0SLionel Sambuc return NULL;
177*ebfedea0SLionel Sambuc return str;
178*ebfedea0SLionel Sambuc }
179*ebfedea0SLionel Sambuc
180*ebfedea0SLionel Sambuc for (msg = context->error; msg; msg = msg->next)
181*ebfedea0SLionel Sambuc p = rk_strpoolprintf(p, "%s%s", msg->msg,
182*ebfedea0SLionel Sambuc msg->next != NULL ? "; " : "");
183*ebfedea0SLionel Sambuc
184*ebfedea0SLionel Sambuc return rk_strpoolcollect(p);
185*ebfedea0SLionel Sambuc }
186*ebfedea0SLionel Sambuc
187*ebfedea0SLionel Sambuc /**
188*ebfedea0SLionel Sambuc * Free error string returned by hx509_get_error_string().
189*ebfedea0SLionel Sambuc *
190*ebfedea0SLionel Sambuc * @param str error string to free.
191*ebfedea0SLionel Sambuc *
192*ebfedea0SLionel Sambuc * @ingroup hx509_error
193*ebfedea0SLionel Sambuc */
194*ebfedea0SLionel Sambuc
195*ebfedea0SLionel Sambuc void
hx509_free_error_string(char * str)196*ebfedea0SLionel Sambuc hx509_free_error_string(char *str)
197*ebfedea0SLionel Sambuc {
198*ebfedea0SLionel Sambuc free(str);
199*ebfedea0SLionel Sambuc }
200*ebfedea0SLionel Sambuc
201*ebfedea0SLionel Sambuc /**
202*ebfedea0SLionel Sambuc * Print error message and fatally exit from error code
203*ebfedea0SLionel Sambuc *
204*ebfedea0SLionel Sambuc * @param context A hx509 context.
205*ebfedea0SLionel Sambuc * @param exit_code exit() code from process.
206*ebfedea0SLionel Sambuc * @param error_code Error code for the reason to exit.
207*ebfedea0SLionel Sambuc * @param fmt format string with the exit message.
208*ebfedea0SLionel Sambuc * @param ... argument to format string.
209*ebfedea0SLionel Sambuc *
210*ebfedea0SLionel Sambuc * @ingroup hx509_error
211*ebfedea0SLionel Sambuc */
212*ebfedea0SLionel Sambuc
213*ebfedea0SLionel Sambuc void
hx509_err(hx509_context context,int exit_code,int error_code,const char * fmt,...)214*ebfedea0SLionel Sambuc hx509_err(hx509_context context, int exit_code,
215*ebfedea0SLionel Sambuc int error_code, const char *fmt, ...)
216*ebfedea0SLionel Sambuc {
217*ebfedea0SLionel Sambuc va_list ap;
218*ebfedea0SLionel Sambuc const char *msg;
219*ebfedea0SLionel Sambuc char *str;
220*ebfedea0SLionel Sambuc
221*ebfedea0SLionel Sambuc va_start(ap, fmt);
222*ebfedea0SLionel Sambuc vasprintf(&str, fmt, ap);
223*ebfedea0SLionel Sambuc va_end(ap);
224*ebfedea0SLionel Sambuc msg = hx509_get_error_string(context, error_code);
225*ebfedea0SLionel Sambuc if (msg == NULL)
226*ebfedea0SLionel Sambuc msg = "no error";
227*ebfedea0SLionel Sambuc
228*ebfedea0SLionel Sambuc errx(exit_code, "%s: %s", str, msg);
229*ebfedea0SLionel Sambuc }
230