os/ossrv/ssl/libcrypto/src/crypto/err/err.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* crypto/err/err.c */
     2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
     3  * All rights reserved.
     4  *
     5  * This package is an SSL implementation written
     6  * by Eric Young (eay@cryptsoft.com).
     7  * The implementation was written so as to conform with Netscapes SSL.
     8  * 
     9  * This library is free for commercial and non-commercial use as long as
    10  * the following conditions are aheared to.  The following conditions
    11  * apply to all code found in this distribution, be it the RC4, RSA,
    12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
    13  * included with this distribution is covered by the same copyright terms
    14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
    15  * 
    16  * Copyright remains Eric Young's, and as such any Copyright notices in
    17  * the code are not to be removed.
    18  * If this package is used in a product, Eric Young should be given attribution
    19  * as the author of the parts of the library used.
    20  * This can be in the form of a textual message at program startup or
    21  * in documentation (online or textual) provided with the package.
    22  * 
    23  * Redistribution and use in source and binary forms, with or without
    24  * modification, are permitted provided that the following conditions
    25  * are met:
    26  * 1. Redistributions of source code must retain the copyright
    27  *    notice, this list of conditions and the following disclaimer.
    28  * 2. Redistributions in binary form must reproduce the above copyright
    29  *    notice, this list of conditions and the following disclaimer in the
    30  *    documentation and/or other materials provided with the distribution.
    31  * 3. All advertising materials mentioning features or use of this software
    32  *    must display the following acknowledgement:
    33  *    "This product includes cryptographic software written by
    34  *     Eric Young (eay@cryptsoft.com)"
    35  *    The word 'cryptographic' can be left out if the rouines from the library
    36  *    being used are not cryptographic related :-).
    37  * 4. If you include any Windows specific code (or a derivative thereof) from 
    38  *    the apps directory (application code) you must include an acknowledgement:
    39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
    40  * 
    41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
    42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    51  * SUCH DAMAGE.
    52  * 
    53  * The licence and distribution terms for any publically available version or
    54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
    55  * copied and put under another distribution licence
    56  * [including the GNU Public Licence.]
    57  */
    58 /* ====================================================================
    59  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
    60  *
    61  * Redistribution and use in source and binary forms, with or without
    62  * modification, are permitted provided that the following conditions
    63  * are met:
    64  *
    65  * 1. Redistributions of source code must retain the above copyright
    66  *    notice, this list of conditions and the following disclaimer. 
    67  *
    68  * 2. Redistributions in binary form must reproduce the above copyright
    69  *    notice, this list of conditions and the following disclaimer in
    70  *    the documentation and/or other materials provided with the
    71  *    distribution.
    72  *
    73  * 3. All advertising materials mentioning features or use of this
    74  *    software must display the following acknowledgment:
    75  *    "This product includes software developed by the OpenSSL Project
    76  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
    77  *
    78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
    79  *    endorse or promote products derived from this software without
    80  *    prior written permission. For written permission, please contact
    81  *    openssl-core@openssl.org.
    82  *
    83  * 5. Products derived from this software may not be called "OpenSSL"
    84  *    nor may "OpenSSL" appear in their names without prior written
    85  *    permission of the OpenSSL Project.
    86  *
    87  * 6. Redistributions of any form whatsoever must retain the following
    88  *    acknowledgment:
    89  *    "This product includes software developed by the OpenSSL Project
    90  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
    91  *
    92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
    93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
    96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   103  * OF THE POSSIBILITY OF SUCH DAMAGE.
   104  * ====================================================================
   105  *
   106  * This product includes cryptographic software written by Eric Young
   107  * (eay@cryptsoft.com).  This product includes software written by Tim
   108  * Hudson (tjh@cryptsoft.com).
   109  *
   110  */
   111  /*
   112  © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
   113  */
   114 
   115 
   116 #include <stdio.h>
   117 #include <stdarg.h>
   118 #include <string.h>
   119 #include "cryptlib.h"
   120 #include <openssl/lhash.h>
   121 #include <openssl/crypto.h>
   122 #include <openssl/buffer.h>
   123 #include <openssl/bio.h>
   124 #include <openssl/err.h>
   125 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
   126 #include "libcrypto_wsd_macros.h"
   127 #include "libcrypto_wsd.h"
   128 #endif
   129 
   130 static void err_load_strings(int lib, ERR_STRING_DATA *str);
   131 static void ERR_STATE_free(ERR_STATE *s);
   132 #ifndef OPENSSL_NO_ERR
   133 #ifndef EMULATOR
   134 static ERR_STRING_DATA ERR_str_libraries[]=
   135 	{
   136 {ERR_PACK(ERR_LIB_NONE,0,0)		,"unknown library"},
   137 {ERR_PACK(ERR_LIB_SYS,0,0)		,"system library"},
   138 {ERR_PACK(ERR_LIB_BN,0,0)		,"bignum routines"},
   139 {ERR_PACK(ERR_LIB_RSA,0,0)		,"rsa routines"},
   140 {ERR_PACK(ERR_LIB_DH,0,0)		,"Diffie-Hellman routines"},
   141 {ERR_PACK(ERR_LIB_EVP,0,0)		,"digital envelope routines"},
   142 {ERR_PACK(ERR_LIB_BUF,0,0)		,"memory buffer routines"},
   143 {ERR_PACK(ERR_LIB_OBJ,0,0)		,"object identifier routines"},
   144 {ERR_PACK(ERR_LIB_PEM,0,0)		,"PEM routines"},
   145 {ERR_PACK(ERR_LIB_DSA,0,0)		,"dsa routines"},
   146 {ERR_PACK(ERR_LIB_X509,0,0)		,"x509 certificate routines"},
   147 {ERR_PACK(ERR_LIB_ASN1,0,0)		,"asn1 encoding routines"},
   148 {ERR_PACK(ERR_LIB_CONF,0,0)		,"configuration file routines"},
   149 {ERR_PACK(ERR_LIB_CRYPTO,0,0)		,"common libcrypto routines"},
   150 {ERR_PACK(ERR_LIB_EC,0,0)		,"elliptic curve routines"},
   151 {ERR_PACK(ERR_LIB_SSL,0,0)		,"SSL routines"},
   152 {ERR_PACK(ERR_LIB_BIO,0,0)		,"BIO routines"},
   153 {ERR_PACK(ERR_LIB_PKCS7,0,0)		,"PKCS7 routines"},
   154 {ERR_PACK(ERR_LIB_X509V3,0,0)		,"X509 V3 routines"},
   155 {ERR_PACK(ERR_LIB_PKCS12,0,0)		,"PKCS12 routines"},
   156 {ERR_PACK(ERR_LIB_RAND,0,0)		,"random number generator"},
   157 {ERR_PACK(ERR_LIB_DSO,0,0)		,"DSO support routines"},
   158 {ERR_PACK(ERR_LIB_ENGINE,0,0)		,"engine routines"},
   159 {ERR_PACK(ERR_LIB_OCSP,0,0)		,"OCSP routines"},
   160 {0,NULL},
   161 	};
   162 
   163 static ERR_STRING_DATA ERR_str_functs[]=
   164 	{
   165 	{ERR_PACK(0,SYS_F_FOPEN,0),     	"fopen"},
   166 	{ERR_PACK(0,SYS_F_CONNECT,0),		"connect"},
   167 	{ERR_PACK(0,SYS_F_GETSERVBYNAME,0),	"getservbyname"},
   168 	{ERR_PACK(0,SYS_F_SOCKET,0),		"socket"}, 
   169 	{ERR_PACK(0,SYS_F_IOCTLSOCKET,0),	"ioctlsocket"},
   170 	{ERR_PACK(0,SYS_F_BIND,0),		"bind"},
   171 	{ERR_PACK(0,SYS_F_LISTEN,0),		"listen"},
   172 	{ERR_PACK(0,SYS_F_ACCEPT,0),		"accept"},
   173 #ifdef OPENSSL_SYS_WINDOWS
   174 	{ERR_PACK(0,SYS_F_WSASTARTUP,0),	"WSAstartup"},
   175 #endif
   176 	{ERR_PACK(0,SYS_F_OPENDIR,0),		"opendir"},
   177 	{ERR_PACK(0,SYS_F_FREAD,0),		"fread"},
   178 	{0,NULL},
   179 	};
   180 
   181 static ERR_STRING_DATA ERR_str_reasons[]=
   182 	{
   183 {ERR_R_SYS_LIB				,"system lib"},
   184 {ERR_R_BN_LIB				,"BN lib"},
   185 {ERR_R_RSA_LIB				,"RSA lib"},
   186 {ERR_R_DH_LIB				,"DH lib"},
   187 {ERR_R_EVP_LIB				,"EVP lib"},
   188 {ERR_R_BUF_LIB				,"BUF lib"},
   189 {ERR_R_OBJ_LIB				,"OBJ lib"},
   190 {ERR_R_PEM_LIB				,"PEM lib"},
   191 {ERR_R_DSA_LIB				,"DSA lib"},
   192 {ERR_R_X509_LIB				,"X509 lib"},
   193 {ERR_R_ASN1_LIB				,"ASN1 lib"},
   194 {ERR_R_CONF_LIB				,"CONF lib"},
   195 {ERR_R_CRYPTO_LIB			,"CRYPTO lib"},
   196 {ERR_R_EC_LIB				,"EC lib"},
   197 {ERR_R_SSL_LIB				,"SSL lib"},
   198 {ERR_R_BIO_LIB				,"BIO lib"},
   199 {ERR_R_PKCS7_LIB			,"PKCS7 lib"},
   200 {ERR_R_X509V3_LIB			,"X509V3 lib"},
   201 {ERR_R_PKCS12_LIB			,"PKCS12 lib"},
   202 {ERR_R_RAND_LIB				,"RAND lib"},
   203 {ERR_R_DSO_LIB				,"DSO lib"},
   204 {ERR_R_ENGINE_LIB			,"ENGINE lib"},
   205 {ERR_R_OCSP_LIB				,"OCSP lib"},
   206 
   207 {ERR_R_NESTED_ASN1_ERROR		,"nested asn1 error"},
   208 {ERR_R_BAD_ASN1_OBJECT_HEADER		,"bad asn1 object header"},
   209 {ERR_R_BAD_GET_ASN1_OBJECT_CALL		,"bad get asn1 object call"},
   210 {ERR_R_EXPECTING_AN_ASN1_SEQUENCE	,"expecting an asn1 sequence"},
   211 {ERR_R_ASN1_LENGTH_MISMATCH		,"asn1 length mismatch"},
   212 {ERR_R_MISSING_ASN1_EOS			,"missing asn1 eos"},
   213 
   214 {ERR_R_FATAL                            ,"fatal"},
   215 {ERR_R_MALLOC_FAILURE			,"malloc failure"},
   216 {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	,"called a function you should not call"},
   217 {ERR_R_PASSED_NULL_PARAMETER		,"passed a null parameter"},
   218 {ERR_R_INTERNAL_ERROR			,"internal error"},
   219 {ERR_R_DISABLED				,"called a function that was disabled at compile-time"},
   220 
   221 {0,NULL},
   222 	};
   223 #else //EMULATOR
   224 const ERR_STRING_DATA temp_ERR_str_libraries[]=
   225 	{
   226 {ERR_PACK(ERR_LIB_NONE,0,0)		,"unknown library"},
   227 {ERR_PACK(ERR_LIB_SYS,0,0)		,"system library"},
   228 {ERR_PACK(ERR_LIB_BN,0,0)		,"bignum routines"},
   229 {ERR_PACK(ERR_LIB_RSA,0,0)		,"rsa routines"},
   230 {ERR_PACK(ERR_LIB_DH,0,0)		,"Diffie-Hellman routines"},
   231 {ERR_PACK(ERR_LIB_EVP,0,0)		,"digital envelope routines"},
   232 {ERR_PACK(ERR_LIB_BUF,0,0)		,"memory buffer routines"},
   233 {ERR_PACK(ERR_LIB_OBJ,0,0)		,"object identifier routines"},
   234 {ERR_PACK(ERR_LIB_PEM,0,0)		,"PEM routines"},
   235 {ERR_PACK(ERR_LIB_DSA,0,0)		,"dsa routines"},
   236 {ERR_PACK(ERR_LIB_X509,0,0)		,"x509 certificate routines"},
   237 {ERR_PACK(ERR_LIB_ASN1,0,0)		,"asn1 encoding routines"},
   238 {ERR_PACK(ERR_LIB_CONF,0,0)		,"configuration file routines"},
   239 {ERR_PACK(ERR_LIB_CRYPTO,0,0)		,"common libcrypto routines"},
   240 {ERR_PACK(ERR_LIB_EC,0,0)		,"elliptic curve routines"},
   241 {ERR_PACK(ERR_LIB_SSL,0,0)		,"SSL routines"},
   242 {ERR_PACK(ERR_LIB_BIO,0,0)		,"BIO routines"},
   243 {ERR_PACK(ERR_LIB_PKCS7,0,0)		,"PKCS7 routines"},
   244 {ERR_PACK(ERR_LIB_X509V3,0,0)		,"X509 V3 routines"},
   245 {ERR_PACK(ERR_LIB_PKCS12,0,0)		,"PKCS12 routines"},
   246 {ERR_PACK(ERR_LIB_RAND,0,0)		,"random number generator"},
   247 {ERR_PACK(ERR_LIB_DSO,0,0)		,"DSO support routines"},
   248 {ERR_PACK(ERR_LIB_ENGINE,0,0)		,"engine routines"},
   249 {ERR_PACK(ERR_LIB_OCSP,0,0)		,"OCSP routines"},
   250 {0,NULL},
   251 	};
   252 
   253 const ERR_STRING_DATA temp_ERR_str_functs[]=
   254 	{
   255 	{ERR_PACK(0,SYS_F_FOPEN,0),     	"fopen"},
   256 	{ERR_PACK(0,SYS_F_CONNECT,0),		"connect"},
   257 	{ERR_PACK(0,SYS_F_GETSERVBYNAME,0),	"getservbyname"},
   258 	{ERR_PACK(0,SYS_F_SOCKET,0),		"socket"}, 
   259 	{ERR_PACK(0,SYS_F_IOCTLSOCKET,0),	"ioctlsocket"},
   260 	{ERR_PACK(0,SYS_F_BIND,0),		"bind"},
   261 	{ERR_PACK(0,SYS_F_LISTEN,0),		"listen"},
   262 	{ERR_PACK(0,SYS_F_ACCEPT,0),		"accept"},
   263 #ifdef OPENSSL_SYS_WINDOWS
   264 	{ERR_PACK(0,SYS_F_WSASTARTUP,0),	"WSAstartup"},
   265 #endif
   266 	{ERR_PACK(0,SYS_F_OPENDIR,0),		"opendir"},
   267 	{ERR_PACK(0,SYS_F_FREAD,0),		"fread"},
   268 	{0,NULL},
   269 	};
   270 
   271 const ERR_STRING_DATA temp_ERR_str_reasons[]=
   272 	{
   273 {ERR_R_SYS_LIB				,"system lib"},
   274 {ERR_R_BN_LIB				,"BN lib"},
   275 {ERR_R_RSA_LIB				,"RSA lib"},
   276 {ERR_R_DH_LIB				,"DH lib"},
   277 {ERR_R_EVP_LIB				,"EVP lib"},
   278 {ERR_R_BUF_LIB				,"BUF lib"},
   279 {ERR_R_OBJ_LIB				,"OBJ lib"},
   280 {ERR_R_PEM_LIB				,"PEM lib"},
   281 {ERR_R_DSA_LIB				,"DSA lib"},
   282 {ERR_R_X509_LIB				,"X509 lib"},
   283 {ERR_R_ASN1_LIB				,"ASN1 lib"},
   284 {ERR_R_CONF_LIB				,"CONF lib"},
   285 {ERR_R_CRYPTO_LIB			,"CRYPTO lib"},
   286 {ERR_R_EC_LIB				,"EC lib"},
   287 {ERR_R_SSL_LIB				,"SSL lib"},
   288 {ERR_R_BIO_LIB				,"BIO lib"},
   289 {ERR_R_PKCS7_LIB			,"PKCS7 lib"},
   290 {ERR_R_X509V3_LIB			,"X509V3 lib"},
   291 {ERR_R_PKCS12_LIB			,"PKCS12 lib"},
   292 {ERR_R_RAND_LIB				,"RAND lib"},
   293 {ERR_R_DSO_LIB				,"DSO lib"},
   294 {ERR_R_ENGINE_LIB			,"ENGINE lib"},
   295 {ERR_R_OCSP_LIB				,"OCSP lib"},
   296 
   297 {ERR_R_NESTED_ASN1_ERROR		,"nested asn1 error"},
   298 {ERR_R_BAD_ASN1_OBJECT_HEADER		,"bad asn1 object header"},
   299 {ERR_R_BAD_GET_ASN1_OBJECT_CALL		,"bad get asn1 object call"},
   300 {ERR_R_EXPECTING_AN_ASN1_SEQUENCE	,"expecting an asn1 sequence"},
   301 {ERR_R_ASN1_LENGTH_MISMATCH		,"asn1 length mismatch"},
   302 {ERR_R_MISSING_ASN1_EOS			,"missing asn1 eos"},
   303 
   304 {ERR_R_FATAL                            ,"fatal"},
   305 {ERR_R_MALLOC_FAILURE			,"malloc failure"},
   306 {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	,"called a function you should not call"},
   307 {ERR_R_PASSED_NULL_PARAMETER		,"passed a null parameter"},
   308 {ERR_R_INTERNAL_ERROR			,"internal error"},
   309 {ERR_R_DISABLED				,"called a function that was disabled at compile-time"},
   310 
   311 {0,NULL},
   312 	};
   313  GET_STATIC_ARRAY_FROM_TLS(ERR_str_functs,err_err,ERR_STRING_DATA)
   314  GET_STATIC_ARRAY_FROM_TLS(ERR_str_reasons,err_err,ERR_STRING_DATA)
   315  GET_STATIC_ARRAY_FROM_TLS(ERR_str_libraries,err_err,ERR_STRING_DATA)
   316  #define ERR_str_functs (GET_WSD_VAR_NAME(ERR_str_functs,err_err, s)())
   317  #define ERR_str_reasons (GET_WSD_VAR_NAME(ERR_str_reasons,err_err, s)())
   318  #define ERR_str_libraries (GET_WSD_VAR_NAME(ERR_str_libraries,err_err, s)())
   319 #endif //EMULATOR
   320 #endif
   321 
   322 #ifndef EMULATOR
   323 /* Define the predeclared (but externally opaque) "ERR_FNS" type */
   324 struct st_ERR_FNS
   325 	{
   326 	/* Works on the "error_hash" string table */
   327 	LHASH *(*cb_err_get)(int create);
   328 	void (*cb_err_del)(void);
   329 	ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
   330 	ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *);
   331 	ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
   332 	/* Works on the "thread_hash" error-state table */
   333 	LHASH *(*cb_thread_get)(int create);
   334 	void (*cb_thread_release)(LHASH **hash);
   335 	ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
   336 	ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
   337 	void (*cb_thread_del_item)(const ERR_STATE *);
   338 	/* Returns the next available error "library" numbers */
   339 	int (*cb_get_next_lib)(void);
   340 	};
   341 #endif
   342 /* Predeclarations of the "err_defaults" functions */
   343 static LHASH *int_err_get(int create);
   344 static void int_err_del(void);
   345 static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
   346 static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
   347 static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
   348 static LHASH *int_thread_get(int create);
   349 static void int_thread_release(LHASH **hash);
   350 static ERR_STATE *int_thread_get_item(const ERR_STATE *);
   351 static ERR_STATE *int_thread_set_item(ERR_STATE *);
   352 static void int_thread_del_item(const ERR_STATE *);
   353 static int int_err_get_next_lib(void);
   354 /* The static ERR_FNS table using these defaults functions */
   355 static const ERR_FNS err_defaults =
   356 	{
   357 	int_err_get,
   358 	int_err_del,
   359 	int_err_get_item,
   360 	int_err_set_item,
   361 	int_err_del_item,
   362 	int_thread_get,
   363 	int_thread_release,
   364 	int_thread_get_item,
   365 	int_thread_set_item,
   366 	int_thread_del_item,
   367 	int_err_get_next_lib
   368 	};
   369 
   370 #ifndef EMULATOR
   371 /* The replacable table of ERR_FNS functions we use at run-time */
   372 static const ERR_FNS *err_fns = NULL;
   373 #else
   374 GET_STATIC_VAR_FROM_TLS(err_fns,err,const ERR_FNS *)
   375 #define err_fns (*GET_WSD_VAR_NAME(err_fns,err, s)())
   376 #endif
   377 
   378 /* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
   379 #define ERRFN(a) err_fns->cb_##a
   380 
   381 #ifndef EMULATOR
   382 /* The internal state used by "err_defaults" - as such, the setting, reading,
   383  * creating, and deleting of this data should only be permitted via the
   384  * "err_defaults" functions. This way, a linked module can completely defer all
   385  * ERR state operation (together with requisite locking) to the implementations
   386  * and state in the loading application. */
   387 static LHASH *int_error_hash = NULL;
   388 static LHASH *int_thread_hash = NULL;
   389 static int int_thread_hash_references = 0;
   390 static int int_err_library_number= ERR_LIB_USER;
   391 #else
   392 GET_STATIC_VAR_FROM_TLS(int_error_hash,err,LHASH *)
   393 #define int_error_hash (*GET_WSD_VAR_NAME(int_error_hash,err,s)())
   394 
   395 GET_STATIC_VAR_FROM_TLS(int_thread_hash,err,LHASH *)
   396 #define int_thread_hash (*GET_WSD_VAR_NAME(int_thread_hash,err,s)())
   397 
   398 GET_STATIC_VAR_FROM_TLS(int_thread_hash_references,err,int)
   399 #define int_thread_hash_references (*GET_WSD_VAR_NAME(int_thread_hash_references,err,s)())
   400 
   401 GET_STATIC_VAR_FROM_TLS(int_err_library_number,err,int)
   402 #define int_err_library_number (*GET_WSD_VAR_NAME(int_err_library_number,err,s)())
   403 
   404 #endif
   405 
   406 /* Internal function that checks whether "err_fns" is set and if not, sets it to
   407  * the defaults. */
   408 static void err_fns_check(void)
   409 	{
   410 	if (err_fns) return;
   411 	
   412 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   413 	if (!err_fns)
   414 		err_fns = &err_defaults;
   415 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   416 	}
   417 
   418 /* API functions to get or set the underlying ERR functions. */
   419 
   420 EXPORT_C const ERR_FNS *ERR_get_implementation(void)
   421 	{
   422 	err_fns_check();
   423 	return err_fns;
   424 	}
   425 
   426 EXPORT_C int ERR_set_implementation(const ERR_FNS *fns)
   427 	{
   428 	int ret = 0;
   429 
   430 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   431 	/* It's too late if 'err_fns' is non-NULL. BTW: not much point setting
   432 	 * an error is there?! */
   433 	if (!err_fns)
   434 		{
   435 		err_fns = fns;
   436 		ret = 1;
   437 		}
   438 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   439 	return ret;
   440 	}
   441 
   442 /* These are the callbacks provided to "lh_new()" when creating the LHASH tables
   443  * internal to the "err_defaults" implementation. */
   444 
   445 /* static unsigned long err_hash(ERR_STRING_DATA *a); */
   446 static unsigned long err_hash(const void *a_void);
   447 /* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */
   448 static int err_cmp(const void *a_void, const void *b_void);
   449 /* static unsigned long pid_hash(ERR_STATE *pid); */
   450 static unsigned long pid_hash(const void *pid_void);
   451 /* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */
   452 static int pid_cmp(const void *a_void,const void *pid_void);
   453 static unsigned long get_error_values(int inc,int top,const char **file,int *line,
   454 				      const char **data,int *flags);
   455 
   456 /* The internal functions used in the "err_defaults" implementation */
   457 
   458 static LHASH *int_err_get(int create)
   459 	{
   460 	LHASH *ret = NULL;
   461 
   462 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   463 	if (!int_error_hash && create)
   464 		{
   465 		CRYPTO_push_info("int_err_get (err.c)");
   466 		int_error_hash = lh_new(err_hash, err_cmp);
   467 		CRYPTO_pop_info();
   468 		}
   469 	if (int_error_hash)
   470 		ret = int_error_hash;
   471 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   472 
   473 	return ret;
   474 	}
   475 
   476 static void int_err_del(void)
   477 	{
   478 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   479 	if (int_error_hash)
   480 		{
   481 		lh_free(int_error_hash);
   482 		int_error_hash = NULL;
   483 		}
   484 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   485 	}
   486 
   487 static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
   488 	{
   489 	ERR_STRING_DATA *p;
   490 	LHASH *hash;
   491 
   492 	err_fns_check();
   493 	hash = ERRFN(err_get)(0);
   494 	if (!hash)
   495 		return NULL;
   496 
   497 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
   498 	p = (ERR_STRING_DATA *)lh_retrieve(hash, d);
   499 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
   500 
   501 	return p;
   502 	}
   503 
   504 static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
   505 	{
   506 	ERR_STRING_DATA *p;
   507 	LHASH *hash;
   508 
   509 	err_fns_check();
   510 	hash = ERRFN(err_get)(1);
   511 	if (!hash)
   512 		return NULL;
   513 
   514 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   515 	p = (ERR_STRING_DATA *)lh_insert(hash, d);
   516 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   517 
   518 	return p;
   519 	}
   520 
   521 static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
   522 	{
   523 	ERR_STRING_DATA *p;
   524 	LHASH *hash;
   525 
   526 	err_fns_check();
   527 	hash = ERRFN(err_get)(0);
   528 	if (!hash)
   529 		return NULL;
   530 
   531 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   532 	p = (ERR_STRING_DATA *)lh_delete(hash, d);
   533 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   534 
   535 	return p;
   536 	}
   537 
   538 static LHASH *int_thread_get(int create)
   539 	{
   540 	LHASH *ret = NULL;
   541 
   542 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   543 	if (!int_thread_hash && create)
   544 		{
   545 		CRYPTO_push_info("int_thread_get (err.c)");
   546 		int_thread_hash = lh_new(pid_hash, pid_cmp);
   547 		CRYPTO_pop_info();
   548 		}
   549 	if (int_thread_hash)
   550 		{
   551 		int_thread_hash_references++;
   552 		ret = int_thread_hash;
   553 		}
   554 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   555 	return ret;
   556 	}
   557 
   558 static void int_thread_release(LHASH **hash)
   559 	{
   560 	int i;
   561 
   562 	if (hash == NULL || *hash == NULL)
   563 		return;
   564 
   565 	i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);
   566 
   567 #ifdef REF_PRINT
   568 	fprintf(stderr,"%4d:%s\n",int_thread_hash_references,"ERR");
   569 #endif
   570 	if (i > 0) return;
   571 #ifdef REF_CHECK
   572 	if (i < 0)
   573 		{
   574 		fprintf(stderr,"int_thread_release, bad reference count\n");
   575 		abort(); /* ok */
   576 		}
   577 #endif
   578 	*hash = NULL;
   579 	}
   580 
   581 static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
   582 	{
   583 	ERR_STATE *p;
   584 	LHASH *hash;
   585 
   586 	err_fns_check();
   587 	hash = ERRFN(thread_get)(0);
   588 	if (!hash)
   589 		return NULL;
   590 
   591 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
   592 	p = (ERR_STATE *)lh_retrieve(hash, d);
   593 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
   594 
   595 	ERRFN(thread_release)(&hash);
   596 	return p;
   597 	}
   598 
   599 static ERR_STATE *int_thread_set_item(ERR_STATE *d)
   600 	{
   601 	ERR_STATE *p;
   602 	LHASH *hash;
   603 
   604 	err_fns_check();
   605 	hash = ERRFN(thread_get)(1);
   606 	if (!hash)
   607 		return NULL;
   608 
   609 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   610 	p = (ERR_STATE *)lh_insert(hash, d);
   611 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   612 
   613 	ERRFN(thread_release)(&hash);
   614 	return p;
   615 	}
   616 
   617 static void int_thread_del_item(const ERR_STATE *d)
   618 	{
   619 	ERR_STATE *p;
   620 	LHASH *hash;
   621 
   622 	err_fns_check();
   623 	hash = ERRFN(thread_get)(0);
   624 	if (!hash)
   625 		return;
   626 
   627 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   628 	p = (ERR_STATE *)lh_delete(hash, d);
   629 	/* make sure we don't leak memory */
   630 	if (int_thread_hash_references == 1
   631 		&& int_thread_hash && (lh_num_items(int_thread_hash) == 0))
   632 		{
   633 		lh_free(int_thread_hash);
   634 		int_thread_hash = NULL;
   635 		}
   636 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   637 
   638 	ERRFN(thread_release)(&hash);
   639 	if (p)
   640 		ERR_STATE_free(p);
   641 	}
   642 
   643 static int int_err_get_next_lib(void)
   644 	{
   645 	int ret;
   646 
   647 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   648 	ret = int_err_library_number++;
   649 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   650 
   651 	return ret;
   652 	}
   653 
   654 
   655 #ifndef OPENSSL_NO_ERR
   656 #define NUM_SYS_STR_REASONS 127
   657 #define LEN_SYS_STR_REASON 32
   658 
   659 #ifndef EMULATOR
   660 static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
   661 #endif
   662 /* SYS_str_reasons is filled with copies of strerror() results at
   663  * initialization.
   664  * 'errno' values up to 127 should cover all usual errors,
   665  * others will be displayed numerically by ERR_error_string.
   666  * It is crucial that we have something for each reason code
   667  * that occurs in ERR_str_reasons, or bogus reason strings
   668  * will be returned for SYSerr(), which always gets an errno
   669  * value and never one of those 'standard' reason codes. */
   670 #ifdef EMULATOR
   671   GET_STATIC_VAR_FROM_TLS(init,err,int)
   672   #define init (*GET_WSD_VAR_NAME(init,err, s)())
   673   GET_STATIC_ARRAY_FROM_TLS(SYS_str_reasons,err,ERR_STRING_DATA)
   674   #define SYS_str_reasons (GET_WSD_VAR_NAME(SYS_str_reasons,err, s)())
   675   
   676   
   677   //GET_STATIC_ARRAY_FROM_TLS(&strerror_tab,err,char)
   678   #define strerror_tab libcrypto_ImpurePtr()->strerror_tab
   679 #endif 
   680 
   681 static void build_SYS_str_reasons(void)
   682 	{
   683 	/* OPENSSL_malloc cannot be used here, use static storage instead */
   684 #ifndef EMULATOR		
   685 	static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
   686 #endif	
   687 	int i;
   688 #ifndef EMULATOR	
   689 	static int init = 1;
   690 #endif	
   691 
   692 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
   693 	if (!init)
   694 		{
   695 		CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
   696 		return;
   697 		}
   698 	
   699 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
   700 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
   701 	if (!init)
   702 		{
   703 		CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   704 		return;
   705 		}
   706 
   707 	for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
   708 		{
   709 		ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
   710 
   711 		str->error = (unsigned long)i;
   712 		if (str->string == NULL)
   713 			{
   714 			char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
   715 			char *src = strerror(i);
   716 			if (src != NULL)
   717 				{
   718 				strncpy(*dest, src, sizeof *dest);
   719 				(*dest)[sizeof *dest - 1] = '\0';
   720 				str->string = *dest;
   721 				}
   722 			}
   723 		if (str->string == NULL)
   724 			str->string = "unknown";
   725 		}
   726 
   727 	/* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
   728 	 * as required by ERR_load_strings. */
   729 
   730 	init = 0;
   731 	
   732 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
   733 	}
   734 #endif
   735 
   736 #define err_clear_data(p,i) \
   737 	do { \
   738 	if (((p)->err_data[i] != NULL) && \
   739 		(p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
   740 		{  \
   741 		OPENSSL_free((p)->err_data[i]); \
   742 		(p)->err_data[i]=NULL; \
   743 		} \
   744 	(p)->err_data_flags[i]=0; \
   745 	} while(0)
   746 
   747 #define err_clear(p,i) \
   748 	do { \
   749 	(p)->err_flags[i]=0; \
   750 	(p)->err_buffer[i]=0; \
   751 	err_clear_data(p,i); \
   752 	(p)->err_file[i]=NULL; \
   753 	(p)->err_line[i]= -1; \
   754 	} while(0)
   755 
   756 static void ERR_STATE_free(ERR_STATE *s)
   757 	{
   758 	int i;
   759 
   760 	if (s == NULL)
   761 	    return;
   762 
   763 	for (i=0; i<ERR_NUM_ERRORS; i++)
   764 		{
   765 		err_clear_data(s,i);
   766 		}
   767 	OPENSSL_free(s);
   768 	}
   769 
   770 EXPORT_C void ERR_load_ERR_strings(void)
   771 	{
   772 	err_fns_check();
   773 #ifndef OPENSSL_NO_ERR
   774 	err_load_strings(0,ERR_str_libraries);
   775 	err_load_strings(0,ERR_str_reasons);
   776 	err_load_strings(ERR_LIB_SYS,ERR_str_functs);
   777 	build_SYS_str_reasons();
   778 	err_load_strings(ERR_LIB_SYS,SYS_str_reasons);
   779 #endif
   780 	}
   781 
   782 static void err_load_strings(int lib, ERR_STRING_DATA *str)
   783 	{
   784 	while (str->error)
   785 		{
   786 		if (lib)
   787 			str->error|=ERR_PACK(lib,0,0);
   788 		ERRFN(err_set_item)(str);
   789 		str++;
   790 		}
   791 	}
   792 
   793 EXPORT_C void ERR_load_strings(int lib, ERR_STRING_DATA *str)
   794 	{
   795 	ERR_load_ERR_strings();
   796 	err_load_strings(lib, str);
   797 	}
   798 
   799 EXPORT_C void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
   800 	{
   801 	while (str->error)
   802 		{
   803 		if (lib)
   804 			str->error|=ERR_PACK(lib,0,0);
   805 		ERRFN(err_del_item)(str);
   806 		str++;
   807 		}
   808 	}
   809 
   810 EXPORT_C void ERR_free_strings(void)
   811 	{
   812 	err_fns_check();
   813 	ERRFN(err_del)();
   814 	}
   815 
   816 /********************************************************/
   817 
   818 EXPORT_C void ERR_put_error(int lib, int func, int reason, const char *file,
   819 	     int line)
   820 	{
   821 	ERR_STATE *es;
   822 
   823 #ifdef _OSD_POSIX
   824 	/* In the BS2000-OSD POSIX subsystem, the compiler generates
   825 	 * path names in the form "*POSIX(/etc/passwd)".
   826 	 * This dirty hack strips them to something sensible.
   827 	 * @@@ We shouldn't modify a const string, though.
   828 	 */
   829 	if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {
   830 		char *end;
   831 
   832 		/* Skip the "*POSIX(" prefix */
   833 		file += sizeof("*POSIX(")-1;
   834 		end = &file[strlen(file)-1];
   835 		if (*end == ')')
   836 			*end = '\0';
   837 		/* Optional: use the basename of the path only. */
   838 		if ((end = strrchr(file, '/')) != NULL)
   839 			file = &end[1];
   840 	}
   841 #endif
   842 	es=ERR_get_state();
   843 
   844 	es->top=(es->top+1)%ERR_NUM_ERRORS;
   845 	if (es->top == es->bottom)
   846 		es->bottom=(es->bottom+1)%ERR_NUM_ERRORS;
   847 	es->err_flags[es->top]=0;
   848 	es->err_buffer[es->top]=ERR_PACK(lib,func,reason);
   849 	es->err_file[es->top]=file;
   850 	es->err_line[es->top]=line;
   851 	err_clear_data(es,es->top);
   852 	}
   853 
   854 EXPORT_C void ERR_clear_error(void)
   855 	{
   856 	int i;
   857 	ERR_STATE *es;
   858 
   859 	es=ERR_get_state();
   860 
   861 	for (i=0; i<ERR_NUM_ERRORS; i++)
   862 		{
   863 		err_clear(es,i);
   864 		}
   865 	es->top=es->bottom=0;
   866 	}
   867 
   868 
   869 EXPORT_C unsigned long ERR_get_error(void)
   870 	{ return(get_error_values(1,0,NULL,NULL,NULL,NULL)); }
   871 
   872 EXPORT_C unsigned long ERR_get_error_line(const char **file,
   873 	     int *line)
   874 	{ return(get_error_values(1,0,file,line,NULL,NULL)); }
   875 
   876 EXPORT_C unsigned long ERR_get_error_line_data(const char **file, int *line,
   877 	     const char **data, int *flags)
   878 	{ return(get_error_values(1,0,file,line,data,flags)); }
   879 
   880 
   881 EXPORT_C unsigned long ERR_peek_error(void)
   882 	{ return(get_error_values(0,0,NULL,NULL,NULL,NULL)); }
   883 
   884 EXPORT_C unsigned long ERR_peek_error_line(const char **file, int *line)
   885 	{ return(get_error_values(0,0,file,line,NULL,NULL)); }
   886 
   887 EXPORT_C unsigned long ERR_peek_error_line_data(const char **file, int *line,
   888 	     const char **data, int *flags)
   889 	{ return(get_error_values(0,0,file,line,data,flags)); }
   890 
   891 
   892 EXPORT_C unsigned long ERR_peek_last_error(void)
   893 	{ return(get_error_values(0,1,NULL,NULL,NULL,NULL)); }
   894 
   895 EXPORT_C unsigned long ERR_peek_last_error_line(const char **file, int *line)
   896 	{ return(get_error_values(0,1,file,line,NULL,NULL)); }
   897 
   898 EXPORT_C unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
   899 	     const char **data, int *flags)
   900 	{ return(get_error_values(0,1,file,line,data,flags)); }
   901 
   902 
   903 static unsigned long get_error_values(int inc, int top, const char **file, int *line,
   904 	     const char **data, int *flags)
   905 	{	
   906 	int i=0;
   907 	ERR_STATE *es;
   908 	unsigned long ret;
   909 
   910 	es=ERR_get_state();
   911 
   912 	if (inc && top)
   913 		{
   914 		if (file) *file = "";
   915 		if (line) *line = 0;
   916 		if (data) *data = "";
   917 		if (flags) *flags = 0;
   918 			
   919 		return ERR_R_INTERNAL_ERROR;
   920 		}
   921 
   922 	if (es->bottom == es->top) return 0;
   923 	if (top)
   924 		i=es->top;			 /* last error */
   925 	else
   926 		i=(es->bottom+1)%ERR_NUM_ERRORS; /* first error */
   927 
   928 	ret=es->err_buffer[i];
   929 	if (inc)
   930 		{
   931 		es->bottom=i;
   932 		es->err_buffer[i]=0;
   933 		}
   934 
   935 	if ((file != NULL) && (line != NULL))
   936 		{
   937 		if (es->err_file[i] == NULL)
   938 			{
   939 			*file="NA";
   940 			if (line != NULL) *line=0;
   941 			}
   942 		else
   943 			{
   944 			*file=es->err_file[i];
   945 			if (line != NULL) *line=es->err_line[i];
   946 			}
   947 		}
   948 
   949 	if (data == NULL)
   950 		{
   951 		if (inc)
   952 			{
   953 			err_clear_data(es, i);
   954 			}
   955 		}
   956 	else
   957 		{
   958 		if (es->err_data[i] == NULL)
   959 			{
   960 			*data="";
   961 			if (flags != NULL) *flags=0;
   962 			}
   963 		else
   964 			{
   965 			*data=es->err_data[i];
   966 			if (flags != NULL) *flags=es->err_data_flags[i];
   967 			}
   968 		}
   969 	return ret;
   970 	}
   971 
   972 EXPORT_C void ERR_error_string_n(unsigned long e, char *buf, size_t len)
   973 	{
   974 	char lsbuf[64], fsbuf[64], rsbuf[64];
   975 	const char *ls,*fs,*rs;
   976 	unsigned long l,f,r;
   977 
   978 	l=ERR_GET_LIB(e);
   979 	f=ERR_GET_FUNC(e);
   980 	r=ERR_GET_REASON(e);
   981 
   982 	ls=ERR_lib_error_string(e);
   983 	fs=ERR_func_error_string(e);
   984 	rs=ERR_reason_error_string(e);
   985 
   986 	if (ls == NULL) 
   987 		BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
   988 	if (fs == NULL)
   989 		BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
   990 	if (rs == NULL)
   991 		BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
   992 
   993 	BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf, 
   994 		fs?fs:fsbuf, rs?rs:rsbuf);
   995 	if (strlen(buf) == len-1)
   996 		{
   997 		/* output may be truncated; make sure we always have 5 
   998 		 * colon-separated fields, i.e. 4 colons ... */
   999 #define NUM_COLONS 4
  1000 		if (len > NUM_COLONS) /* ... if possible */
  1001 			{
  1002 			int i;
  1003 			char *s = buf;
  1004 			
  1005 			for (i = 0; i < NUM_COLONS; i++)
  1006 				{
  1007 				char *colon = strchr(s, ':');
  1008 				if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i)
  1009 					{
  1010 					/* set colon no. i at last possible position
  1011 					 * (buf[len-1] is the terminating 0)*/
  1012 					colon = &buf[len-1] - NUM_COLONS + i;
  1013 					*colon = ':';
  1014 					}
  1015 				s = colon + 1;
  1016 				}
  1017 			}
  1018 		}
  1019 	}
  1020 
  1021 #ifdef EMULATOR	
  1022 GET_STATIC_ARRAY_FROM_TLS(buf,err,char)
  1023 #define buf (GET_WSD_VAR_NAME(buf,err, s)())
  1024 #endif	
  1025 
  1026 /* BAD for multi-threading: uses a local buffer if ret == NULL */
  1027 /* ERR_error_string_n should be used instead for ret != NULL
  1028  * as ERR_error_string cannot know how large the buffer is */
  1029 EXPORT_C char *ERR_error_string(unsigned long e, char *ret)
  1030 	{
  1031 #ifndef EMULATOR	
  1032 	static char buf[256];
  1033 #endif	
  1034 
  1035 	if (ret == NULL) ret=buf;
  1036 	ERR_error_string_n(e, ret, 256);
  1037 
  1038 	return ret;
  1039 	}
  1040 
  1041 EXPORT_C LHASH *ERR_get_string_table(void)
  1042 	{
  1043 	err_fns_check();
  1044 	return ERRFN(err_get)(0);
  1045 	}
  1046 
  1047 EXPORT_C LHASH *ERR_get_err_state_table(void)
  1048 	{
  1049 	err_fns_check();
  1050 	return ERRFN(thread_get)(0);
  1051 	}
  1052 
  1053 EXPORT_C void ERR_release_err_state_table(LHASH **hash)
  1054 	{
  1055 	err_fns_check();
  1056 	ERRFN(thread_release)(hash);
  1057 	}
  1058 
  1059 EXPORT_C const char *ERR_lib_error_string(unsigned long e)
  1060 	{
  1061 	ERR_STRING_DATA d,*p;
  1062 	unsigned long l;
  1063 
  1064 	err_fns_check();
  1065 	l=ERR_GET_LIB(e);
  1066 	d.error=ERR_PACK(l,0,0);
  1067 	p=ERRFN(err_get_item)(&d);
  1068 	return((p == NULL)?NULL:p->string);
  1069 	}
  1070 
  1071 EXPORT_C const char *ERR_func_error_string(unsigned long e)
  1072 	{
  1073 	ERR_STRING_DATA d,*p;
  1074 	unsigned long l,f;
  1075 
  1076 	err_fns_check();
  1077 	l=ERR_GET_LIB(e);
  1078 	f=ERR_GET_FUNC(e);
  1079 	d.error=ERR_PACK(l,f,0);
  1080 	p=ERRFN(err_get_item)(&d);
  1081 	return((p == NULL)?NULL:p->string);
  1082 	}
  1083 
  1084 EXPORT_C const char *ERR_reason_error_string(unsigned long e)
  1085 	{
  1086 	ERR_STRING_DATA d,*p=NULL;
  1087 	unsigned long l,r;
  1088 
  1089 	err_fns_check();
  1090 	l=ERR_GET_LIB(e);
  1091 	r=ERR_GET_REASON(e);
  1092 	d.error=ERR_PACK(l,0,r);
  1093 	p=ERRFN(err_get_item)(&d);
  1094 	if (!p)
  1095 		{
  1096 		d.error=ERR_PACK(0,0,r);
  1097 		p=ERRFN(err_get_item)(&d);
  1098 		}
  1099 	return((p == NULL)?NULL:p->string);
  1100 	}
  1101 
  1102 /* static unsigned long err_hash(ERR_STRING_DATA *a) */
  1103 static unsigned long err_hash(const void *a_void)
  1104 	{
  1105 	unsigned long ret,l;
  1106 
  1107 	l=((const ERR_STRING_DATA *)a_void)->error;
  1108 	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
  1109 	return(ret^ret%19*13);
  1110 	}
  1111 
  1112 /* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */
  1113 static int err_cmp(const void *a_void, const void *b_void)
  1114 	{
  1115 	return((int)(((const ERR_STRING_DATA *)a_void)->error -
  1116 			((const ERR_STRING_DATA *)b_void)->error));
  1117 	}
  1118 
  1119 /* static unsigned long pid_hash(ERR_STATE *a) */
  1120 static unsigned long pid_hash(const void *a_void)
  1121 	{
  1122 	return(((const ERR_STATE *)a_void)->pid*13);
  1123 	}
  1124 
  1125 /* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
  1126 static int pid_cmp(const void *a_void, const void *b_void)
  1127 	{
  1128 	return((int)((long)((const ERR_STATE *)a_void)->pid -
  1129 			(long)((const ERR_STATE *)b_void)->pid));
  1130 	}
  1131 
  1132 EXPORT_C void ERR_remove_state(unsigned long pid)
  1133 	{
  1134 	ERR_STATE tmp;
  1135 
  1136 	err_fns_check();
  1137 	if (pid == 0)
  1138 		pid=(unsigned long)CRYPTO_thread_id();
  1139 	tmp.pid=pid;
  1140 	/* thread_del_item automatically destroys the LHASH if the number of
  1141 	 * items reaches zero. */
  1142 	ERRFN(thread_del_item)(&tmp);
  1143 	}
  1144 #ifdef EMULATOR
  1145 GET_STATIC_VAR_FROM_TLS(fallback,err,ERR_STATE)
  1146 #define fallback (*GET_WSD_VAR_NAME(fallback,err, s)())
  1147 #endif
  1148 EXPORT_C ERR_STATE *ERR_get_state(void)
  1149 	{
  1150 #ifndef EMULATOR	
  1151 	static ERR_STATE fallback;
  1152 #endif	
  1153 	ERR_STATE *ret,tmp,*tmpp=NULL;
  1154 	int i;
  1155 	unsigned long pid;
  1156 
  1157 	err_fns_check();
  1158 	pid=(unsigned long)CRYPTO_thread_id();
  1159 	tmp.pid=pid;
  1160 	ret=ERRFN(thread_get_item)(&tmp);
  1161 
  1162 	/* ret == the error state, if NULL, make a new one */
  1163 	if (ret == NULL)
  1164 		{
  1165 		ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
  1166 		if (ret == NULL) return(&fallback);
  1167 		ret->pid=pid;
  1168 		ret->top=0;
  1169 		ret->bottom=0;
  1170 		for (i=0; i<ERR_NUM_ERRORS; i++)
  1171 			{
  1172 			ret->err_data[i]=NULL;
  1173 			ret->err_data_flags[i]=0;
  1174 			}
  1175 		tmpp = ERRFN(thread_set_item)(ret);
  1176 		/* To check if insertion failed, do a get. */
  1177 		if (ERRFN(thread_get_item)(ret) != ret)
  1178 			{
  1179 			ERR_STATE_free(ret); /* could not insert it */
  1180 			return(&fallback);
  1181 			}
  1182 		/* If a race occured in this function and we came second, tmpp
  1183 		 * is the first one that we just replaced. */
  1184 		if (tmpp)
  1185 			ERR_STATE_free(tmpp);
  1186 		}
  1187 	return ret;
  1188 	}
  1189 
  1190 EXPORT_C int ERR_get_next_error_library(void)
  1191 	{
  1192 	err_fns_check();
  1193 	return ERRFN(get_next_lib)();
  1194 	}
  1195 
  1196 EXPORT_C void ERR_set_error_data(char *data, int flags)
  1197 	{
  1198 	ERR_STATE *es;
  1199 	int i;
  1200 
  1201 	es=ERR_get_state();
  1202 
  1203 	i=es->top;
  1204 	if (i == 0)
  1205 		i=ERR_NUM_ERRORS-1;
  1206 
  1207 	err_clear_data(es,i);
  1208 	es->err_data[i]=data;
  1209 	es->err_data_flags[i]=flags;
  1210 	}
  1211 
  1212 EXPORT_C void ERR_add_error_data(int num, ...)
  1213 	{
  1214 	va_list args;
  1215 	int i,n,s;
  1216 	char *str,*p,*a;
  1217 
  1218 	s=80;
  1219 	str=OPENSSL_malloc(s+1);
  1220 	if (str == NULL) return;
  1221 	str[0]='\0';
  1222 
  1223 	va_start(args, num);
  1224 	n=0;
  1225 	for (i=0; i<num; i++)
  1226 		{
  1227 		a=va_arg(args, char*);
  1228 		/* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
  1229 		if (a != NULL)
  1230 			{
  1231 			n+=strlen(a);
  1232 			if (n > s)
  1233 				{
  1234 				s=n+20;
  1235 				p=OPENSSL_realloc(str,s+1);
  1236 				if (p == NULL)
  1237 					{
  1238 					OPENSSL_free(str);
  1239 					goto err;
  1240 					}
  1241 				else
  1242 					str=p;
  1243 				}
  1244 			BUF_strlcat(str,a,(size_t)s+1);
  1245 			}
  1246 		}
  1247 	ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);
  1248 
  1249 err:
  1250 	va_end(args);
  1251 	}
  1252 
  1253 EXPORT_C int ERR_set_mark(void)
  1254 	{
  1255 	ERR_STATE *es;
  1256 
  1257 	es=ERR_get_state();
  1258 
  1259 	if (es->bottom == es->top) return 0;
  1260 	es->err_flags[es->top]|=ERR_FLAG_MARK;
  1261 	return 1;
  1262 	}
  1263 
  1264 EXPORT_C int ERR_pop_to_mark(void)
  1265 	{
  1266 	ERR_STATE *es;
  1267 
  1268 	es=ERR_get_state();
  1269 
  1270 	while(es->bottom != es->top
  1271 		&& (es->err_flags[es->top] & ERR_FLAG_MARK) == 0)
  1272 		{
  1273 		err_clear(es,es->top);
  1274 		es->top-=1;
  1275 		if (es->top == -1) es->top=ERR_NUM_ERRORS;
  1276 		}
  1277 		
  1278 	if (es->bottom == es->top) return 0;
  1279 	es->err_flags[es->top]&=~ERR_FLAG_MARK;
  1280 	return 1;
  1281 	}