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 48/** 49 * Resets the error strings the hx509 context. 50 * 51 * @param context A hx509 context. 52 * 53 * @ingroup hx509_error 54 */ 55 56void 57hx509_clear_error_string(hx509_context context) 58{ 59 if (context) { 60 heim_release(context->error); 61 context->error = NULL; 62 } 63} 64 65/** 66 * Add an error message to the hx509 context. 67 * 68 * @param context A hx509 context. 69 * @param flags 70 * - HX509_ERROR_APPEND appends the error string to the old messages 71 (code is updated). 72 * @param code error code related to error message 73 * @param fmt error message format 74 * @param ap arguments to error message format 75 * 76 * @ingroup hx509_error 77 */ 78 79void 80hx509_set_error_stringv(hx509_context context, int flags, int code, 81 const char *fmt, va_list ap) 82{ 83 heim_error_t msg; 84 85 if (context == NULL) 86 return; 87 88 msg = heim_error_createv(code, fmt, ap); 89 if (msg) { 90 if (flags & HX509_ERROR_APPEND) 91 heim_error_append(msg, context->error); 92 heim_release(context->error); 93 } 94 context->error = msg; 95} 96 97/** 98 * See hx509_set_error_stringv(). 99 * 100 * @param context A hx509 context. 101 * @param flags 102 * - HX509_ERROR_APPEND appends the error string to the old messages 103 (code is updated). 104 * @param code error code related to error message 105 * @param fmt error message format 106 * @param ... arguments to error message format 107 * 108 * @ingroup hx509_error 109 */ 110 111void 112hx509_set_error_string(hx509_context context, int flags, int code, 113 const char *fmt, ...) 114{ 115 va_list ap; 116 117 va_start(ap, fmt); 118 hx509_set_error_stringv(context, flags, code, fmt, ap); 119 va_end(ap); 120} 121 122/** 123 * Get an error string from context associated with error_code. 124 * 125 * @param context A hx509 context. 126 * @param error_code Get error message for this error code. 127 * 128 * @return error string, free with hx509_free_error_string(). 129 * 130 * @ingroup hx509_error 131 */ 132 133char * 134hx509_get_error_string(hx509_context context, int error_code) 135{ 136 heim_error_t msg = context->error; 137 heim_string_t s; 138 char *str = NULL; 139 const char *cstr; 140 141 if (msg == NULL || heim_error_get_code(msg) != error_code) { 142 char buf[256]; 143 144 cstr = com_right_r(context->et_list, error_code, buf, sizeof(buf)); 145 if (cstr) 146 return strdup(cstr); 147 cstr = strerror(error_code); 148 if (cstr) 149 return strdup(cstr); 150 if (asprintf(&str, "<unknown error: %d>", error_code) == -1) 151 return NULL; 152 return str; 153 } 154 155 s = heim_error_copy_string(msg); 156 if (s) { 157 str = heim_string_copy_utf8(s); 158 heim_release(s); 159 } 160 return str; 161} 162 163/** 164 * Free error string returned by hx509_get_error_string(). 165 * 166 * @param str error string to free. 167 * 168 * @ingroup hx509_error 169 */ 170 171void 172hx509_free_error_string(char *str) 173{ 174 free(str); 175} 176 177/** 178 * Print error message and fatally exit from error code 179 * 180 * @param context A hx509 context. 181 * @param exit_code exit() code from process. 182 * @param error_code Error code for the reason to exit. 183 * @param fmt format string with the exit message. 184 * @param ... argument to format string. 185 * 186 * @ingroup hx509_error 187 */ 188 189void 190hx509_err(hx509_context context, int exit_code, 191 int error_code, const char *fmt, ...) 192{ 193 va_list ap; 194 const char *msg; 195 char *str; 196 197 va_start(ap, fmt); 198 vasprintf(&str, fmt, ap); 199 va_end(ap); 200 msg = hx509_get_error_string(context, error_code); 201 if (msg == NULL) 202 msg = "no error"; 203 204 errx(exit_code, "%s: %s", str, msg); 205} 206