/*1* Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include "hx_locl.h"3435/**36* @page page_error Hx509 error reporting functions37*38* See the library functions here: @ref hx509_error39*/4041struct hx509_error_data {42hx509_error next;43int code;44char *msg;45};4647static void48free_error_string(hx509_error msg)49{50while(msg) {51hx509_error m2 = msg->next;52free(msg->msg);53free(msg);54msg = m2;55}56}5758/**59* Resets the error strings the hx509 context.60*61* @param context A hx509 context.62*63* @ingroup hx509_error64*/6566void67hx509_clear_error_string(hx509_context context)68{69if (context) {70free_error_string(context->error);71context->error = NULL;72}73}7475/**76* Add an error message to the hx509 context.77*78* @param context A hx509 context.79* @param flags80* - HX509_ERROR_APPEND appends the error string to the old messages81(code is updated).82* @param code error code related to error message83* @param fmt error message format84* @param ap arguments to error message format85*86* @ingroup hx509_error87*/8889void90hx509_set_error_stringv(hx509_context context, int flags, int code,91const char *fmt, va_list ap)92{93hx509_error msg;9495if (context == NULL)96return;9798msg = calloc(1, sizeof(*msg));99if (msg == NULL) {100hx509_clear_error_string(context);101return;102}103104if (vasprintf(&msg->msg, fmt, ap) == -1) {105hx509_clear_error_string(context);106free(msg);107return;108}109msg->code = code;110111if (flags & HX509_ERROR_APPEND) {112msg->next = context->error;113context->error = msg;114} else {115free_error_string(context->error);116context->error = msg;117}118}119120/**121* See hx509_set_error_stringv().122*123* @param context A hx509 context.124* @param flags125* - HX509_ERROR_APPEND appends the error string to the old messages126(code is updated).127* @param code error code related to error message128* @param fmt error message format129* @param ... arguments to error message format130*131* @ingroup hx509_error132*/133134void135hx509_set_error_string(hx509_context context, int flags, int code,136const char *fmt, ...)137{138va_list ap;139140va_start(ap, fmt);141hx509_set_error_stringv(context, flags, code, fmt, ap);142va_end(ap);143}144145/**146* Get an error string from context associated with error_code.147*148* @param context A hx509 context.149* @param error_code Get error message for this error code.150*151* @return error string, free with hx509_free_error_string().152*153* @ingroup hx509_error154*/155156char *157hx509_get_error_string(hx509_context context, int error_code)158{159struct rk_strpool *p = NULL;160hx509_error msg = context->error;161162if (msg == NULL || msg->code != error_code) {163const char *cstr;164char *str;165166cstr = com_right(context->et_list, error_code);167if (cstr)168return strdup(cstr);169cstr = strerror(error_code);170if (cstr)171return strdup(cstr);172if (asprintf(&str, "<unknown error: %d>", error_code) == -1)173return NULL;174return str;175}176177for (msg = context->error; msg; msg = msg->next)178p = rk_strpoolprintf(p, "%s%s", msg->msg,179msg->next != NULL ? "; " : "");180181return rk_strpoolcollect(p);182}183184/**185* Free error string returned by hx509_get_error_string().186*187* @param str error string to free.188*189* @ingroup hx509_error190*/191192void193hx509_free_error_string(char *str)194{195free(str);196}197198/**199* Print error message and fatally exit from error code200*201* @param context A hx509 context.202* @param exit_code exit() code from process.203* @param error_code Error code for the reason to exit.204* @param fmt format string with the exit message.205* @param ... argument to format string.206*207* @ingroup hx509_error208*/209210void211hx509_err(hx509_context context, int exit_code,212int error_code, const char *fmt, ...)213{214va_list ap;215const char *msg;216char *str;217218va_start(ap, fmt);219vasprintf(&str, fmt, ap);220va_end(ap);221msg = hx509_get_error_string(context, error_code);222if (msg == NULL)223msg = "no error";224225errx(exit_code, "%s: %s", str, msg);226}227228229