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