1/* 2 * Copyright (c) 2006 - 2007 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 "hx_locl.h" 35 36/** 37 * @page page_error Hx509 error reporting functions 38 * 39 * See the library functions here: @ref hx509_error 40 */ 41 42struct hx509_error_data { 43 hx509_error next; 44 int code; 45 char *msg; 46}; 47 48static void 49free_error_string(hx509_error msg) 50{ 51 while(msg) { 52 hx509_error m2 = msg->next; 53 free(msg->msg); 54 free(msg); 55 msg = m2; 56 } 57} 58 59/** 60 * Resets the error strings the hx509 context. 61 * 62 * @param context A hx509 context. 63 * 64 * @ingroup hx509_error 65 */ 66 67void 68hx509_clear_error_string(hx509_context context) 69{ 70 free_error_string(context->error); 71 context->error = NULL; 72} 73 74/** 75 * Add an error message to the hx509 context. 76 * 77 * @param context A hx509 context. 78 * @param flags 79 * - HX509_ERROR_APPEND appends the error string to the old messages 80 (code is updated). 81 * @param code error code related to error message 82 * @param fmt error message format 83 * @param ap arguments to error message format 84 * 85 * @ingroup hx509_error 86 */ 87 88void 89hx509_set_error_stringv(hx509_context context, int flags, int code, 90 const char *fmt, va_list ap) 91{ 92 hx509_error msg; 93 94 msg = calloc(1, sizeof(*msg)); 95 if (msg == NULL) { 96 hx509_clear_error_string(context); 97 return; 98 } 99 100 if (vasprintf(&msg->msg, fmt, ap) == -1) { 101 hx509_clear_error_string(context); 102 free(msg); 103 return; 104 } 105 msg->code = code; 106 107 if (flags & HX509_ERROR_APPEND) { 108 msg->next = context->error; 109 context->error = msg; 110 } else { 111 free_error_string(context->error); 112 context->error = msg; 113 } 114} 115 116/** 117 * See hx509_set_error_stringv(). 118 * 119 * @param context A hx509 context. 120 * @param flags 121 * - HX509_ERROR_APPEND appends the error string to the old messages 122 (code is updated). 123 * @param code error code related to error message 124 * @param fmt error message format 125 * @param ... arguments to error message format 126 * 127 * @ingroup hx509_error 128 */ 129 130void 131hx509_set_error_string(hx509_context context, int flags, int code, 132 const char *fmt, ...) 133{ 134 va_list ap; 135 136 va_start(ap, fmt); 137 hx509_set_error_stringv(context, flags, code, fmt, ap); 138 va_end(ap); 139} 140 141/** 142 * Get an error string from context associated with error_code. 143 * 144 * @param context A hx509 context. 145 * @param error_code Get error message for this error code. 146 * 147 * @return error string, free with hx509_free_error_string(). 148 * 149 * @ingroup hx509_error 150 */ 151 152char * 153hx509_get_error_string(hx509_context context, int error_code) 154{ 155 struct rk_strpool *p = NULL; 156 hx509_error msg = context->error; 157 158 if (msg == NULL || msg->code != error_code) { 159 const char *cstr; 160 char *str; 161 162 cstr = com_right(context->et_list, error_code); 163 if (cstr) 164 return strdup(cstr); 165 cstr = strerror(error_code); 166 if (cstr) 167 return strdup(cstr); 168 if (asprintf(&str, "<unknown error: %d>", error_code) == -1) 169 return NULL; 170 return str; 171 } 172 173 for (msg = context->error; msg; msg = msg->next) 174 p = rk_strpoolprintf(p, "%s%s", msg->msg, 175 msg->next != NULL ? "; " : ""); 176 177 return rk_strpoolcollect(p); 178} 179 180/** 181 * Free error string returned by hx509_get_error_string(). 182 * 183 * @param str error string to free. 184 * 185 * @ingroup hx509_error 186 */ 187 188void 189hx509_free_error_string(char *str) 190{ 191 free(str); 192} 193 194/** 195 * Print error message and fatally exit from error code 196 * 197 * @param context A hx509 context. 198 * @param exit_code exit() code from process. 199 * @param error_code Error code for the reason to exit. 200 * @param fmt format string with the exit message. 201 * @param ... argument to format string. 202 * 203 * @ingroup hx509_error 204 */ 205 206void 207hx509_err(hx509_context context, int exit_code, 208 int error_code, const char *fmt, ...) 209{ 210 va_list ap; 211 const char *msg; 212 char *str; 213 214 va_start(ap, fmt); 215 vasprintf(&str, fmt, ap); 216 va_end(ap); 217 msg = hx509_get_error_string(context, error_code); 218 if (msg == NULL) 219 msg = "no error"; 220 221 errx(exit_code, "%s: %s", str, msg); 222} 223