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