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