1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "libuutil_common.h" 30 31 #include <assert.h> 32 #include <errno.h> 33 #include <libintl.h> 34 #include <pthread.h> 35 #include <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <sys/debug.h> 40 #include <thread.h> 41 #include <unistd.h> 42 43 #if !defined(TEXT_DOMAIN) 44 #define TEXT_DOMAIN "SYS_TEST" 45 #endif 46 47 static pthread_mutex_t uu_key_lock = PTHREAD_MUTEX_INITIALIZER; 48 static pthread_key_t uu_error_key; 49 static int uu_error_key_setup; 50 51 static pthread_mutex_t uu_panic_lock = PTHREAD_MUTEX_INITIALIZER; 52 /* LINTED static unused */ 53 static const char *uu_panic_format; 54 /* LINTED static unused */ 55 static va_list uu_panic_args; 56 static pthread_t uu_panic_thread; 57 58 static uint32_t _uu_main_error; 59 60 void 61 uu_set_error(uint_t code) 62 { 63 int error; 64 if (thr_main() != 0) { 65 _uu_main_error = code; 66 return; 67 } 68 if (uu_error_key_setup == 0) { 69 (void) pthread_mutex_lock(&uu_key_lock); 70 if (uu_error_key_setup == 0) { 71 error = pthread_key_create(&uu_error_key, NULL); 72 if (error != 0) 73 uu_error_key_setup = -1; 74 else 75 uu_error_key_setup = 1; 76 } 77 (void) pthread_mutex_unlock(&uu_key_lock); 78 } 79 if (uu_error_key_setup > 0) 80 (void) pthread_setspecific(uu_error_key, 81 (void *)(uintptr_t)code); 82 } 83 84 uint32_t 85 uu_error(void) 86 { 87 if (thr_main() != 0) 88 return (_uu_main_error); 89 90 if (uu_error_key_setup < 0) 91 return (UU_ERROR_UNKNOWN); 92 else if (uu_error_key_setup == 0) 93 return (UU_ERROR_NONE); 94 else 95 return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key)); 96 } 97 98 const char * 99 uu_strerror(uint32_t code) 100 { 101 const char *str; 102 103 switch (code) { 104 case UU_ERROR_NONE: 105 str = dgettext(TEXT_DOMAIN, "No error"); 106 break; 107 108 case UU_ERROR_INVALID_ARGUMENT: 109 str = dgettext(TEXT_DOMAIN, "Invalid argument"); 110 break; 111 112 case UU_ERROR_UNKNOWN_FLAG: 113 str = dgettext(TEXT_DOMAIN, "Unknown flag passed"); 114 break; 115 116 case UU_ERROR_NO_MEMORY: 117 str = dgettext(TEXT_DOMAIN, "Out of memory"); 118 break; 119 120 case UU_ERROR_CALLBACK_FAILED: 121 str = dgettext(TEXT_DOMAIN, "Callback-initiated failure"); 122 break; 123 124 case UU_ERROR_NOT_SUPPORTED: 125 str = dgettext(TEXT_DOMAIN, "Operation not supported"); 126 break; 127 128 case UU_ERROR_EMPTY: 129 str = dgettext(TEXT_DOMAIN, "No value provided"); 130 break; 131 132 case UU_ERROR_UNDERFLOW: 133 str = dgettext(TEXT_DOMAIN, "Value too small"); 134 break; 135 136 case UU_ERROR_OVERFLOW: 137 str = dgettext(TEXT_DOMAIN, "Value too large"); 138 break; 139 140 case UU_ERROR_INVALID_CHAR: 141 str = dgettext(TEXT_DOMAIN, 142 "Value contains unexpected character"); 143 break; 144 145 case UU_ERROR_INVALID_DIGIT: 146 str = dgettext(TEXT_DOMAIN, 147 "Value contains digit not in base"); 148 break; 149 150 case UU_ERROR_SYSTEM: 151 str = dgettext(TEXT_DOMAIN, "Underlying system error"); 152 break; 153 154 case UU_ERROR_UNKNOWN: 155 str = dgettext(TEXT_DOMAIN, "Error status not known"); 156 break; 157 158 default: 159 errno = ESRCH; 160 str = NULL; 161 break; 162 } 163 return (str); 164 } 165 166 void 167 uu_panic(const char *format, ...) 168 { 169 va_list args; 170 171 va_start(args, format); 172 173 (void) pthread_mutex_lock(&uu_panic_lock); 174 if (uu_panic_thread == 0) { 175 uu_panic_thread = pthread_self(); 176 uu_panic_format = format; 177 va_copy(uu_panic_args, args); 178 } 179 (void) pthread_mutex_unlock(&uu_panic_lock); 180 181 (void) vfprintf(stderr, format, args); 182 183 if (uu_panic_thread == pthread_self()) 184 abort(); 185 else 186 for (;;) 187 (void) pause(); 188 } 189 190 int 191 assfail(const char *astring, const char *file, int line) 192 { 193 __assert(astring, file, line); 194 /*NOTREACHED*/ 195 return (0); 196 } 197 198 static void 199 uu_lockup(void) 200 { 201 (void) pthread_mutex_lock(&uu_panic_lock); 202 (void) pthread_mutex_lock(&uu_key_lock); 203 uu_avl_lockup(); 204 uu_list_lockup(); 205 } 206 207 static void 208 uu_release(void) 209 { 210 (void) pthread_mutex_unlock(&uu_panic_lock); 211 (void) pthread_mutex_unlock(&uu_key_lock); 212 uu_avl_release(); 213 uu_list_release(); 214 } 215 216 static void 217 uu_release_child(void) 218 { 219 uu_panic_format = NULL; 220 uu_panic_thread = 0; 221 222 uu_release(); 223 } 224 225 #pragma init(uu_init) 226 static void 227 uu_init(void) 228 { 229 (void) pthread_atfork(uu_lockup, uu_release, uu_release_child); 230 } 231