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