1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * CDDL HEADER START 3*eda14cbcSMatt Macy * 4*eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5*eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6*eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7*eda14cbcSMatt Macy * 8*eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10*eda14cbcSMatt Macy * See the License for the specific language governing permissions 11*eda14cbcSMatt Macy * and limitations under the License. 12*eda14cbcSMatt Macy * 13*eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14*eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16*eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17*eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18*eda14cbcSMatt Macy * 19*eda14cbcSMatt Macy * CDDL HEADER END 20*eda14cbcSMatt Macy */ 21*eda14cbcSMatt Macy 22*eda14cbcSMatt Macy /* 23*eda14cbcSMatt Macy * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24*eda14cbcSMatt Macy */ 25*eda14cbcSMatt Macy 26*eda14cbcSMatt Macy #include "libuutil_common.h" 27*eda14cbcSMatt Macy 28*eda14cbcSMatt Macy #include <assert.h> 29*eda14cbcSMatt Macy #include <errno.h> 30*eda14cbcSMatt Macy #include <libintl.h> 31*eda14cbcSMatt Macy #include <pthread.h> 32*eda14cbcSMatt Macy #include <stdarg.h> 33*eda14cbcSMatt Macy #include <stdio.h> 34*eda14cbcSMatt Macy #include <stdlib.h> 35*eda14cbcSMatt Macy #include <string.h> 36*eda14cbcSMatt Macy #include <sys/debug.h> 37*eda14cbcSMatt Macy #include <unistd.h> 38*eda14cbcSMatt Macy #include <ctype.h> 39*eda14cbcSMatt Macy 40*eda14cbcSMatt Macy #if !defined(TEXT_DOMAIN) 41*eda14cbcSMatt Macy #define TEXT_DOMAIN "SYS_TEST" 42*eda14cbcSMatt Macy #endif 43*eda14cbcSMatt Macy 44*eda14cbcSMatt Macy /* 45*eda14cbcSMatt Macy * All of the old code under !defined(PTHREAD_ONCE_KEY_NP) 46*eda14cbcSMatt Macy * is here to enable the building of a native version of 47*eda14cbcSMatt Macy * libuutil.so when the build machine has not yet been upgraded 48*eda14cbcSMatt Macy * to a version of libc that provides pthread_key_create_once_np(). 49*eda14cbcSMatt Macy * It should all be deleted when solaris_nevada ships. 50*eda14cbcSMatt Macy * The code is not MT-safe in a relaxed memory model. 51*eda14cbcSMatt Macy */ 52*eda14cbcSMatt Macy 53*eda14cbcSMatt Macy #if defined(PTHREAD_ONCE_KEY_NP) 54*eda14cbcSMatt Macy static pthread_key_t uu_error_key = PTHREAD_ONCE_KEY_NP; 55*eda14cbcSMatt Macy #else /* PTHREAD_ONCE_KEY_NP */ 56*eda14cbcSMatt Macy static pthread_key_t uu_error_key = 0; 57*eda14cbcSMatt Macy static pthread_mutex_t uu_key_lock = PTHREAD_MUTEX_INITIALIZER; 58*eda14cbcSMatt Macy #endif /* PTHREAD_ONCE_KEY_NP */ 59*eda14cbcSMatt Macy 60*eda14cbcSMatt Macy static int uu_error_key_setup = 0; 61*eda14cbcSMatt Macy 62*eda14cbcSMatt Macy static pthread_mutex_t uu_panic_lock = PTHREAD_MUTEX_INITIALIZER; 63*eda14cbcSMatt Macy /* LINTED static unused */ 64*eda14cbcSMatt Macy static const char *uu_panic_format; 65*eda14cbcSMatt Macy /* LINTED static unused */ 66*eda14cbcSMatt Macy static va_list uu_panic_args; 67*eda14cbcSMatt Macy static pthread_t uu_panic_thread; 68*eda14cbcSMatt Macy 69*eda14cbcSMatt Macy static uint32_t _uu_main_error; 70*eda14cbcSMatt Macy static __thread int _uu_main_thread = 0; 71*eda14cbcSMatt Macy 72*eda14cbcSMatt Macy void 73*eda14cbcSMatt Macy uu_set_error(uint_t code) 74*eda14cbcSMatt Macy { 75*eda14cbcSMatt Macy if (_uu_main_thread) { 76*eda14cbcSMatt Macy _uu_main_error = code; 77*eda14cbcSMatt Macy return; 78*eda14cbcSMatt Macy } 79*eda14cbcSMatt Macy #if defined(PTHREAD_ONCE_KEY_NP) 80*eda14cbcSMatt Macy if (pthread_key_create_once_np(&uu_error_key, NULL) != 0) 81*eda14cbcSMatt Macy uu_error_key_setup = -1; 82*eda14cbcSMatt Macy else 83*eda14cbcSMatt Macy uu_error_key_setup = 1; 84*eda14cbcSMatt Macy #else /* PTHREAD_ONCE_KEY_NP */ 85*eda14cbcSMatt Macy if (uu_error_key_setup == 0) { 86*eda14cbcSMatt Macy (void) pthread_mutex_lock(&uu_key_lock); 87*eda14cbcSMatt Macy if (uu_error_key_setup == 0) { 88*eda14cbcSMatt Macy if (pthread_key_create(&uu_error_key, NULL) != 0) 89*eda14cbcSMatt Macy uu_error_key_setup = -1; 90*eda14cbcSMatt Macy else 91*eda14cbcSMatt Macy uu_error_key_setup = 1; 92*eda14cbcSMatt Macy } 93*eda14cbcSMatt Macy (void) pthread_mutex_unlock(&uu_key_lock); 94*eda14cbcSMatt Macy } 95*eda14cbcSMatt Macy #endif /* PTHREAD_ONCE_KEY_NP */ 96*eda14cbcSMatt Macy if (uu_error_key_setup > 0) 97*eda14cbcSMatt Macy (void) pthread_setspecific(uu_error_key, 98*eda14cbcSMatt Macy (void *)(uintptr_t)code); 99*eda14cbcSMatt Macy } 100*eda14cbcSMatt Macy 101*eda14cbcSMatt Macy uint32_t 102*eda14cbcSMatt Macy uu_error(void) 103*eda14cbcSMatt Macy { 104*eda14cbcSMatt Macy if (_uu_main_thread) 105*eda14cbcSMatt Macy return (_uu_main_error); 106*eda14cbcSMatt Macy 107*eda14cbcSMatt Macy if (uu_error_key_setup < 0) /* can't happen? */ 108*eda14cbcSMatt Macy return (UU_ERROR_UNKNOWN); 109*eda14cbcSMatt Macy 110*eda14cbcSMatt Macy /* 111*eda14cbcSMatt Macy * Because UU_ERROR_NONE == 0, if uu_set_error() was 112*eda14cbcSMatt Macy * never called, then this will return UU_ERROR_NONE: 113*eda14cbcSMatt Macy */ 114*eda14cbcSMatt Macy return ((uint32_t)(uintptr_t)pthread_getspecific(uu_error_key)); 115*eda14cbcSMatt Macy } 116*eda14cbcSMatt Macy 117*eda14cbcSMatt Macy const char * 118*eda14cbcSMatt Macy uu_strerror(uint32_t code) 119*eda14cbcSMatt Macy { 120*eda14cbcSMatt Macy const char *str; 121*eda14cbcSMatt Macy 122*eda14cbcSMatt Macy switch (code) { 123*eda14cbcSMatt Macy case UU_ERROR_NONE: 124*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "No error"); 125*eda14cbcSMatt Macy break; 126*eda14cbcSMatt Macy 127*eda14cbcSMatt Macy case UU_ERROR_INVALID_ARGUMENT: 128*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Invalid argument"); 129*eda14cbcSMatt Macy break; 130*eda14cbcSMatt Macy 131*eda14cbcSMatt Macy case UU_ERROR_UNKNOWN_FLAG: 132*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Unknown flag passed"); 133*eda14cbcSMatt Macy break; 134*eda14cbcSMatt Macy 135*eda14cbcSMatt Macy case UU_ERROR_NO_MEMORY: 136*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Out of memory"); 137*eda14cbcSMatt Macy break; 138*eda14cbcSMatt Macy 139*eda14cbcSMatt Macy case UU_ERROR_CALLBACK_FAILED: 140*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Callback-initiated failure"); 141*eda14cbcSMatt Macy break; 142*eda14cbcSMatt Macy 143*eda14cbcSMatt Macy case UU_ERROR_NOT_SUPPORTED: 144*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Operation not supported"); 145*eda14cbcSMatt Macy break; 146*eda14cbcSMatt Macy 147*eda14cbcSMatt Macy case UU_ERROR_EMPTY: 148*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "No value provided"); 149*eda14cbcSMatt Macy break; 150*eda14cbcSMatt Macy 151*eda14cbcSMatt Macy case UU_ERROR_UNDERFLOW: 152*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Value too small"); 153*eda14cbcSMatt Macy break; 154*eda14cbcSMatt Macy 155*eda14cbcSMatt Macy case UU_ERROR_OVERFLOW: 156*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Value too large"); 157*eda14cbcSMatt Macy break; 158*eda14cbcSMatt Macy 159*eda14cbcSMatt Macy case UU_ERROR_INVALID_CHAR: 160*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, 161*eda14cbcSMatt Macy "Value contains unexpected character"); 162*eda14cbcSMatt Macy break; 163*eda14cbcSMatt Macy 164*eda14cbcSMatt Macy case UU_ERROR_INVALID_DIGIT: 165*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, 166*eda14cbcSMatt Macy "Value contains digit not in base"); 167*eda14cbcSMatt Macy break; 168*eda14cbcSMatt Macy 169*eda14cbcSMatt Macy case UU_ERROR_SYSTEM: 170*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Underlying system error"); 171*eda14cbcSMatt Macy break; 172*eda14cbcSMatt Macy 173*eda14cbcSMatt Macy case UU_ERROR_UNKNOWN: 174*eda14cbcSMatt Macy str = dgettext(TEXT_DOMAIN, "Error status not known"); 175*eda14cbcSMatt Macy break; 176*eda14cbcSMatt Macy 177*eda14cbcSMatt Macy default: 178*eda14cbcSMatt Macy errno = ESRCH; 179*eda14cbcSMatt Macy str = NULL; 180*eda14cbcSMatt Macy break; 181*eda14cbcSMatt Macy } 182*eda14cbcSMatt Macy return (str); 183*eda14cbcSMatt Macy } 184*eda14cbcSMatt Macy 185*eda14cbcSMatt Macy void 186*eda14cbcSMatt Macy uu_panic(const char *format, ...) 187*eda14cbcSMatt Macy { 188*eda14cbcSMatt Macy va_list args; 189*eda14cbcSMatt Macy 190*eda14cbcSMatt Macy va_start(args, format); 191*eda14cbcSMatt Macy 192*eda14cbcSMatt Macy (void) pthread_mutex_lock(&uu_panic_lock); 193*eda14cbcSMatt Macy if (uu_panic_thread == 0) { 194*eda14cbcSMatt Macy uu_panic_thread = pthread_self(); 195*eda14cbcSMatt Macy uu_panic_format = format; 196*eda14cbcSMatt Macy va_copy(uu_panic_args, args); 197*eda14cbcSMatt Macy } 198*eda14cbcSMatt Macy (void) pthread_mutex_unlock(&uu_panic_lock); 199*eda14cbcSMatt Macy 200*eda14cbcSMatt Macy (void) vfprintf(stderr, format, args); 201*eda14cbcSMatt Macy 202*eda14cbcSMatt Macy va_end(args); 203*eda14cbcSMatt Macy 204*eda14cbcSMatt Macy if (uu_panic_thread == pthread_self()) 205*eda14cbcSMatt Macy abort(); 206*eda14cbcSMatt Macy else 207*eda14cbcSMatt Macy for (;;) 208*eda14cbcSMatt Macy (void) pause(); 209*eda14cbcSMatt Macy } 210*eda14cbcSMatt Macy 211*eda14cbcSMatt Macy static void 212*eda14cbcSMatt Macy uu_lockup(void) 213*eda14cbcSMatt Macy { 214*eda14cbcSMatt Macy (void) pthread_mutex_lock(&uu_panic_lock); 215*eda14cbcSMatt Macy #if !defined(PTHREAD_ONCE_KEY_NP) 216*eda14cbcSMatt Macy (void) pthread_mutex_lock(&uu_key_lock); 217*eda14cbcSMatt Macy #endif 218*eda14cbcSMatt Macy uu_avl_lockup(); 219*eda14cbcSMatt Macy uu_list_lockup(); 220*eda14cbcSMatt Macy } 221*eda14cbcSMatt Macy 222*eda14cbcSMatt Macy static void 223*eda14cbcSMatt Macy uu_release(void) 224*eda14cbcSMatt Macy { 225*eda14cbcSMatt Macy (void) pthread_mutex_unlock(&uu_panic_lock); 226*eda14cbcSMatt Macy #if !defined(PTHREAD_ONCE_KEY_NP) 227*eda14cbcSMatt Macy (void) pthread_mutex_unlock(&uu_key_lock); 228*eda14cbcSMatt Macy #endif 229*eda14cbcSMatt Macy uu_avl_release(); 230*eda14cbcSMatt Macy uu_list_release(); 231*eda14cbcSMatt Macy } 232*eda14cbcSMatt Macy 233*eda14cbcSMatt Macy static void 234*eda14cbcSMatt Macy uu_release_child(void) 235*eda14cbcSMatt Macy { 236*eda14cbcSMatt Macy uu_panic_format = NULL; 237*eda14cbcSMatt Macy uu_panic_thread = 0; 238*eda14cbcSMatt Macy 239*eda14cbcSMatt Macy uu_release(); 240*eda14cbcSMatt Macy } 241*eda14cbcSMatt Macy 242*eda14cbcSMatt Macy #ifdef __GNUC__ 243*eda14cbcSMatt Macy static void 244*eda14cbcSMatt Macy uu_init(void) __attribute__((constructor)); 245*eda14cbcSMatt Macy #else 246*eda14cbcSMatt Macy #pragma init(uu_init) 247*eda14cbcSMatt Macy #endif 248*eda14cbcSMatt Macy 249*eda14cbcSMatt Macy static void 250*eda14cbcSMatt Macy uu_init(void) 251*eda14cbcSMatt Macy { 252*eda14cbcSMatt Macy _uu_main_thread = 1; 253*eda14cbcSMatt Macy (void) pthread_atfork(uu_lockup, uu_release, uu_release_child); 254*eda14cbcSMatt Macy } 255*eda14cbcSMatt Macy 256*eda14cbcSMatt Macy /* 257*eda14cbcSMatt Macy * Dump a block of memory in hex+ascii, for debugging 258*eda14cbcSMatt Macy */ 259*eda14cbcSMatt Macy void 260*eda14cbcSMatt Macy uu_dump(FILE *out, const char *prefix, const void *buf, size_t len) 261*eda14cbcSMatt Macy { 262*eda14cbcSMatt Macy const unsigned char *p = buf; 263*eda14cbcSMatt Macy int i; 264*eda14cbcSMatt Macy 265*eda14cbcSMatt Macy for (i = 0; i < len; i += 16) { 266*eda14cbcSMatt Macy int j; 267*eda14cbcSMatt Macy 268*eda14cbcSMatt Macy (void) fprintf(out, "%s", prefix); 269*eda14cbcSMatt Macy for (j = 0; j < 16 && i + j < len; j++) { 270*eda14cbcSMatt Macy (void) fprintf(out, "%2.2x ", p[i + j]); 271*eda14cbcSMatt Macy } 272*eda14cbcSMatt Macy for (; j < 16; j++) { 273*eda14cbcSMatt Macy (void) fprintf(out, " "); 274*eda14cbcSMatt Macy } 275*eda14cbcSMatt Macy for (j = 0; j < 16 && i + j < len; j++) { 276*eda14cbcSMatt Macy (void) fprintf(out, "%c", 277*eda14cbcSMatt Macy isprint(p[i + j]) ? p[i + j] : '.'); 278*eda14cbcSMatt Macy } 279*eda14cbcSMatt Macy (void) fprintf(out, "\n"); 280*eda14cbcSMatt Macy } 281*eda14cbcSMatt Macy } 282