error.c revision 178825
1109998Smarkm/*
2280304Sjkim * Copyright (c) 2006 - 2007 Kungliga Tekniska H�gskolan
3280304Sjkim * (Royal Institute of Technology, Stockholm, Sweden).
4280304Sjkim * All rights reserved.
5109998Smarkm *
6109998Smarkm * Redistribution and use in source and binary forms, with or without
7160814Ssimon * modification, are permitted provided that the following conditions
8109998Smarkm * are met:
9109998Smarkm *
10109998Smarkm * 1. Redistributions of source code must retain the above copyright
11109998Smarkm *    notice, this list of conditions and the following disclaimer.
12109998Smarkm *
13109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
14280304Sjkim *    notice, this list of conditions and the following disclaimer in the
15109998Smarkm *    documentation and/or other materials provided with the distribution.
16109998Smarkm *
17109998Smarkm * 3. Neither the name of the Institute nor the names of its contributors
18109998Smarkm *    may be used to endorse or promote products derived from this software
19109998Smarkm *    without specific prior written permission.
20109998Smarkm *
21109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22109998Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24109998Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25109998Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26109998Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27109998Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29109998Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30109998Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31109998Smarkm * SUCH DAMAGE.
32109998Smarkm */
33109998Smarkm
34109998Smarkm#include "hx_locl.h"
35109998SmarkmRCSID("$Id: error.c 22332 2007-12-17 01:03:22Z lha $");
36109998Smarkm
37109998Smarkm/**
38109998Smarkm * @page page_error Hx509 error reporting functions
39109998Smarkm *
40109998Smarkm * See the library functions here: @ref hx509_error
41109998Smarkm */
42109998Smarkm
43109998Smarkmstruct hx509_error_data {
44109998Smarkm    hx509_error next;
45109998Smarkm    int code;
46109998Smarkm    char *msg;
47109998Smarkm};
48109998Smarkm
49109998Smarkmstatic void
50109998Smarkmfree_error_string(hx509_error msg)
51109998Smarkm{
52109998Smarkm    while(msg) {
53109998Smarkm	hx509_error m2 = msg->next;
54109998Smarkm	free(msg->msg);
55109998Smarkm	free(msg);
56109998Smarkm	msg = m2;
57109998Smarkm    }
58109998Smarkm}
59160814Ssimon
60160814Ssimon/**
61280304Sjkim * Resets the error strings the hx509 context.
62160814Ssimon *
63160814Ssimon * @param context A hx509 context.
64109998Smarkm *
65109998Smarkm * @ingroup hx509_error
66280304Sjkim */
67109998Smarkm
68280304Sjkimvoid
69111147Snectarhx509_clear_error_string(hx509_context context)
70280304Sjkim{
71280304Sjkim    free_error_string(context->error);
72280304Sjkim    context->error = NULL;
73111147Snectar}
74280304Sjkim
75280304Sjkim/**
76280304Sjkim * Add an error message to the hx509 context.
77280304Sjkim *
78280304Sjkim * @param context A hx509 context.
79280304Sjkim * @param flags
80280304Sjkim * - HX509_ERROR_APPEND appends the error string to the old messages
81280304Sjkim     (code is updated).
82280304Sjkim * @param code error code related to error message
83280304Sjkim * @param fmt error message format
84280304Sjkim * @param ap arguments to error message format
85280304Sjkim *
86280304Sjkim * @ingroup hx509_error
87280304Sjkim */
88280304Sjkim
89280304Sjkimvoid
90280304Sjkimhx509_set_error_stringv(hx509_context context, int flags, int code,
91280304Sjkim			const char *fmt, va_list ap)
92280304Sjkim{
93280304Sjkim    hx509_error msg;
94280304Sjkim
95109998Smarkm    msg = calloc(1, sizeof(*msg));
96280304Sjkim    if (msg == NULL) {
97280304Sjkim	hx509_clear_error_string(context);
98160814Ssimon	return;
99280304Sjkim    }
100238405Sjkim
101109998Smarkm    if (vasprintf(&msg->msg, fmt, ap) == -1) {
102109998Smarkm	hx509_clear_error_string(context);
103109998Smarkm	free(msg);
104109998Smarkm	return;
105280304Sjkim    }
106280304Sjkim    msg->code = code;
107280304Sjkim
108280304Sjkim    if (flags & HX509_ERROR_APPEND) {
109280304Sjkim	msg->next = context->error;
110280304Sjkim	context->error = msg;
111280304Sjkim    } else  {
112280304Sjkim	free_error_string(context->error);
113280304Sjkim	context->error = msg;
114280304Sjkim    }
115280304Sjkim}
116280304Sjkim
117280304Sjkim/**
118280304Sjkim * See hx509_set_error_stringv().
119280304Sjkim *
120109998Smarkm * @param context A hx509 context.
121280304Sjkim * @param flags
122280304Sjkim * - HX509_ERROR_APPEND appends the error string to the old messages
123109998Smarkm     (code is updated).
124280304Sjkim * @param code error code related to error message
125280304Sjkim * @param fmt error message format
126280304Sjkim * @param ... arguments to error message format
127280304Sjkim *
128280304Sjkim * @ingroup hx509_error
129280304Sjkim */
130280304Sjkim
131109998Smarkmvoid
132109998Smarkmhx509_set_error_string(hx509_context context, int flags, int code,
133280304Sjkim		       const char *fmt, ...)
134280304Sjkim{
135109998Smarkm    va_list ap;
136280304Sjkim
137280304Sjkim    va_start(ap, fmt);
138280304Sjkim    hx509_set_error_stringv(context, flags, code, fmt, ap);
139280304Sjkim    va_end(ap);
140280304Sjkim}
141280304Sjkim
142280304Sjkim/**
143109998Smarkm * Get an error string from context associated with error_code.
144280304Sjkim *
145280304Sjkim * @param context A hx509 context.
146280304Sjkim * @param error_code Get error message for this error code.
147280304Sjkim *
148280304Sjkim * @return error string, free with hx509_free_error_string().
149280304Sjkim *
150280304Sjkim * @ingroup hx509_error
151280304Sjkim */
152280304Sjkim
153280304Sjkimchar *
154280304Sjkimhx509_get_error_string(hx509_context context, int error_code)
155109998Smarkm{
156280304Sjkim    struct rk_strpool *p = NULL;
157280304Sjkim    hx509_error msg = context->error;
158280304Sjkim
159280304Sjkim    if (msg == NULL || msg->code != error_code) {
160238405Sjkim	const char *cstr;
161238405Sjkim	char *str;
162280304Sjkim
163238405Sjkim	cstr = com_right(context->et_list, error_code);
164280304Sjkim	if (cstr)
165280304Sjkim	    return strdup(cstr);
166280304Sjkim	cstr = strerror(error_code);
167280304Sjkim	if (cstr)
168280304Sjkim	    return strdup(cstr);
169280304Sjkim	if (asprintf(&str, "<unknown error: %d>", error_code) == -1)
170280304Sjkim	    return NULL;
171280304Sjkim	return str;
172280304Sjkim    }
173280304Sjkim
174280304Sjkim    for (msg = context->error; msg; msg = msg->next)
175109998Smarkm	p = rk_strpoolprintf(p, "%s%s", msg->msg,
176109998Smarkm			     msg->next != NULL ? "; " : "");
177280304Sjkim
178280304Sjkim    return rk_strpoolcollect(p);
179280304Sjkim}
180280304Sjkim
181280304Sjkim/**
182280304Sjkim * Free error string returned by hx509_get_error_string().
183280304Sjkim *
184280304Sjkim * @param str error string to free.
185280304Sjkim *
186280304Sjkim * @ingroup hx509_error
187280304Sjkim */
188280304Sjkim
189280304Sjkimvoid
190109998Smarkmhx509_free_error_string(char *str)
191280304Sjkim{
192280304Sjkim    free(str);
193280304Sjkim}
194109998Smarkm
195280304Sjkim/**
196280304Sjkim * Print error message and fatally exit from error code
197280304Sjkim *
198280304Sjkim * @param context A hx509 context.
199280304Sjkim * @param exit_code exit() code from process.
200280304Sjkim * @param error_code Error code for the reason to exit.
201280304Sjkim * @param fmt format string with the exit message.
202280304Sjkim * @param ... argument to format string.
203280304Sjkim *
204280304Sjkim * @ingroup hx509_error
205109998Smarkm */
206280304Sjkim
207280304Sjkimvoid
208280304Sjkimhx509_err(hx509_context context, int exit_code,
209280304Sjkim	  int error_code, const char *fmt, ...)
210280304Sjkim{
211280304Sjkim    va_list ap;
212280304Sjkim    const char *msg;
213280304Sjkim    char *str;
214280304Sjkim
215280304Sjkim    va_start(ap, fmt);
216280304Sjkim    vasprintf(&str, fmt, ap);
217280304Sjkim    va_end(ap);
218280304Sjkim    msg = hx509_get_error_string(context, error_code);
219280304Sjkim    if (msg == NULL)
220280304Sjkim	msg = "no error";
221280304Sjkim
222280304Sjkim    errx(exit_code, "%s: %s", str, msg);
223280304Sjkim}
224280304Sjkim