xref: /illumos-gate/usr/src/lib/libuutil/common/uu_misc.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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