]>
Commit | Line | Data |
---|---|---|
d02b48c6 | 1 | /* crypto/err/err.c */ |
58964a49 | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
d02b48c6 RE |
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 | #include <stdio.h> | |
60 | #include "lhash.h" | |
61 | #include "crypto.h" | |
62 | #include "cryptlib.h" | |
63 | #include "buffer.h" | |
64 | #include "err.h" | |
65 | #include "crypto.h" | |
66 | ||
67 | ||
68 | static LHASH *error_hash=NULL; | |
69 | static LHASH *thread_hash=NULL; | |
70 | ||
71 | #ifndef NOPROTO | |
72 | static unsigned long err_hash(ERR_STRING_DATA *a); | |
73 | static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); | |
74 | static unsigned long pid_hash(ERR_STATE *pid); | |
75 | static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); | |
58964a49 RE |
76 | static unsigned long get_error_values(int inc,char **file,int *line, |
77 | char **data,int *flags); | |
78 | static void ERR_STATE_free(ERR_STATE *s); | |
d02b48c6 RE |
79 | #else |
80 | static unsigned long err_hash(); | |
81 | static int err_cmp(); | |
82 | static unsigned long pid_hash(); | |
83 | static int pid_cmp(); | |
dfeab068 | 84 | static unsigned long get_error_values(); |
58964a49 RE |
85 | static void ERR_STATE_free(); |
86 | ERR_STATE *s; | |
d02b48c6 RE |
87 | #endif |
88 | ||
89 | #ifndef NO_ERR | |
90 | static ERR_STRING_DATA ERR_str_libraries[]= | |
91 | { | |
92 | {ERR_PACK(ERR_LIB_NONE,0,0) ,"unknown library"}, | |
93 | {ERR_PACK(ERR_LIB_SYS,0,0) ,"system library"}, | |
94 | {ERR_PACK(ERR_LIB_BN,0,0) ,"bignum routines"}, | |
95 | {ERR_PACK(ERR_LIB_RSA,0,0) ,"rsa routines"}, | |
96 | {ERR_PACK(ERR_LIB_DH,0,0) ,"Diffie-Hellman routines"}, | |
97 | {ERR_PACK(ERR_LIB_EVP,0,0) ,"digital envelope routines"}, | |
98 | {ERR_PACK(ERR_LIB_BUF,0,0) ,"memory buffer routines"}, | |
99 | {ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"}, | |
100 | {ERR_PACK(ERR_LIB_OBJ,0,0) ,"object identifier routines"}, | |
101 | {ERR_PACK(ERR_LIB_PEM,0,0) ,"PEM routines"}, | |
102 | {ERR_PACK(ERR_LIB_ASN1,0,0) ,"asn1 encoding routines"}, | |
103 | {ERR_PACK(ERR_LIB_X509,0,0) ,"x509 certificate routines"}, | |
104 | {ERR_PACK(ERR_LIB_CONF,0,0) ,"configuation file routines"}, | |
105 | {ERR_PACK(ERR_LIB_METH,0,0) ,"X509 lookup 'method' routines"}, | |
106 | {ERR_PACK(ERR_LIB_SSL,0,0) ,"SSL routines"}, | |
107 | {ERR_PACK(ERR_LIB_RSAREF,0,0) ,"RSAref routines"}, | |
108 | {ERR_PACK(ERR_LIB_PROXY,0,0) ,"Proxy routines"}, | |
109 | {ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"}, | |
110 | {ERR_PACK(ERR_LIB_PKCS7,0,0) ,"PKCS7 routines"}, | |
111 | {0,NULL}, | |
112 | }; | |
113 | ||
114 | static ERR_STRING_DATA ERR_str_functs[]= | |
115 | { | |
116 | {ERR_PACK(0,SYS_F_FOPEN,0), "fopen"}, | |
117 | {ERR_PACK(0,SYS_F_CONNECT,0), "connect"}, | |
118 | {ERR_PACK(0,SYS_F_GETSERVBYNAME,0), "getservbyname"}, | |
119 | {ERR_PACK(0,SYS_F_SOCKET,0), "socket"}, | |
120 | {ERR_PACK(0,SYS_F_IOCTLSOCKET,0), "ioctlsocket"}, | |
121 | {ERR_PACK(0,SYS_F_BIND,0), "bind"}, | |
122 | {ERR_PACK(0,SYS_F_LISTEN,0), "listen"}, | |
123 | {ERR_PACK(0,SYS_F_ACCEPT,0), "accept"}, | |
124 | #ifdef WINDOWS | |
125 | {ERR_PACK(0,SYS_F_WSASTARTUP,0), "WSAstartup"}, | |
126 | #endif | |
127 | {0,NULL}, | |
128 | }; | |
129 | ||
130 | static ERR_STRING_DATA ERR_str_reasons[]= | |
131 | { | |
132 | {ERR_R_FATAL ,"fatal"}, | |
133 | {ERR_R_SYS_LIB ,"system lib"}, | |
134 | {ERR_R_BN_LIB ,"BN lib"}, | |
135 | {ERR_R_RSA_LIB ,"RSA lib"}, | |
136 | {ERR_R_DH_LIB ,"DH lib"}, | |
137 | {ERR_R_EVP_LIB ,"EVP lib"}, | |
138 | {ERR_R_BUF_LIB ,"BUF lib"}, | |
139 | {ERR_R_BIO_LIB ,"BIO lib"}, | |
140 | {ERR_R_OBJ_LIB ,"OBJ lib"}, | |
141 | {ERR_R_PEM_LIB ,"PEM lib"}, | |
142 | {ERR_R_X509_LIB ,"X509 lib"}, | |
143 | {ERR_R_METH_LIB ,"METH lib"}, | |
144 | {ERR_R_ASN1_LIB ,"ASN1 lib"}, | |
145 | {ERR_R_CONF_LIB ,"CONF lib"}, | |
146 | {ERR_R_SSL_LIB ,"SSL lib"}, | |
147 | {ERR_R_PROXY_LIB ,"PROXY lib"}, | |
148 | {ERR_R_BIO_LIB ,"BIO lib"}, | |
149 | {ERR_R_PKCS7_LIB ,"PKCS7 lib"}, | |
150 | {ERR_R_MALLOC_FAILURE ,"Malloc failure"}, | |
151 | {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED ,"called a fuction you should not call"}, | |
dfeab068 RE |
152 | {ERR_R_PASSED_NULL_PARAMETER ,"passed a null parameter"}, |
153 | {ERR_R_NESTED_ASN1_ERROR ,"nested asn1 error"}, | |
154 | {ERR_R_BAD_ASN1_OBJECT_HEADER ,"bad asn1 object header"}, | |
155 | {ERR_R_BAD_GET_ASN1_OBJECT_CALL ,"bad get asn1 object call"}, | |
156 | {ERR_R_EXPECTING_AN_ASN1_SEQUENCE ,"expecting an asn1 sequence"}, | |
157 | {ERR_R_ASN1_LENGTH_MISMATCH ,"asn1 length mismatch"}, | |
158 | {ERR_R_MISSING_ASN1_EOS ,"missing asn1 eos"}, | |
159 | ||
d02b48c6 RE |
160 | {0,NULL}, |
161 | }; | |
162 | #endif | |
163 | ||
58964a49 RE |
164 | #define err_clear_data(p,i) \ |
165 | if (((p)->err_data[i] != NULL) && \ | |
166 | (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \ | |
167 | { \ | |
168 | Free((p)->err_data[i]); \ | |
169 | (p)->err_data[i]=NULL; \ | |
170 | } \ | |
171 | (p)->err_data_flags[i]=0; | |
172 | ||
173 | static void ERR_STATE_free(s) | |
174 | ERR_STATE *s; | |
175 | { | |
176 | int i; | |
177 | ||
178 | for (i=0; i<ERR_NUM_ERRORS; i++) | |
179 | { | |
180 | err_clear_data(s,i); | |
181 | } | |
182 | Free(s); | |
183 | } | |
184 | ||
d02b48c6 RE |
185 | void ERR_load_ERR_strings() |
186 | { | |
187 | static int init=1; | |
188 | ||
189 | if (init) | |
190 | { | |
191 | CRYPTO_w_lock(CRYPTO_LOCK_ERR); | |
192 | if (init == 0) | |
193 | { | |
194 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR); | |
195 | return; | |
196 | } | |
197 | init=0; | |
198 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR); | |
199 | ||
200 | #ifndef NO_ERR | |
201 | ERR_load_strings(0,ERR_str_libraries); | |
202 | ERR_load_strings(0,ERR_str_reasons); | |
203 | ERR_load_strings(ERR_LIB_SYS,ERR_str_functs); | |
204 | #endif | |
205 | } | |
206 | } | |
207 | ||
208 | void ERR_load_strings(lib,str) | |
209 | int lib; | |
210 | ERR_STRING_DATA *str; | |
211 | { | |
212 | if (error_hash == NULL) | |
213 | { | |
214 | CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH); | |
215 | error_hash=lh_new(err_hash,err_cmp); | |
216 | if (error_hash == NULL) | |
217 | { | |
218 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH); | |
219 | return; | |
220 | } | |
221 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH); | |
222 | ||
223 | ERR_load_ERR_strings(); | |
224 | } | |
225 | ||
226 | CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH); | |
227 | while (str->error) | |
228 | { | |
229 | str->error|=ERR_PACK(lib,0,0); | |
230 | lh_insert(error_hash,(char *)str); | |
231 | str++; | |
232 | } | |
233 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH); | |
234 | } | |
235 | ||
236 | void ERR_free_strings() | |
237 | { | |
238 | CRYPTO_w_lock(CRYPTO_LOCK_ERR); | |
239 | ||
240 | if (error_hash != NULL) | |
241 | { | |
242 | lh_free(error_hash); | |
243 | error_hash=NULL; | |
244 | } | |
245 | ||
246 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR); | |
247 | } | |
248 | ||
58964a49 RE |
249 | /********************************************************/ |
250 | ||
d02b48c6 RE |
251 | void ERR_put_error(lib,func,reason,file,line) |
252 | int lib,func,reason; | |
253 | char *file; | |
254 | int line; | |
255 | { | |
256 | ERR_STATE *es; | |
257 | ||
258 | es=ERR_get_state(); | |
259 | ||
260 | es->top=(es->top+1)%ERR_NUM_ERRORS; | |
261 | if (es->top == es->bottom) | |
262 | es->bottom=(es->bottom+1)%ERR_NUM_ERRORS; | |
263 | es->err_buffer[es->top]=ERR_PACK(lib,func,reason); | |
264 | es->err_file[es->top]=file; | |
265 | es->err_line[es->top]=line; | |
58964a49 | 266 | err_clear_data(es,es->top); |
d02b48c6 RE |
267 | } |
268 | ||
269 | void ERR_clear_error() | |
270 | { | |
d02b48c6 RE |
271 | ERR_STATE *es; |
272 | ||
273 | es=ERR_get_state(); | |
274 | ||
58964a49 RE |
275 | #if 0 |
276 | /* hmm... is this needed */ | |
d02b48c6 RE |
277 | for (i=0; i<ERR_NUM_ERRORS; i++) |
278 | { | |
279 | es->err_buffer[i]=0; | |
280 | es->err_file[i]=NULL; | |
281 | es->err_line[i]= -1; | |
58964a49 | 282 | err_clear_data(es,i); |
d02b48c6 | 283 | } |
58964a49 | 284 | #endif |
d02b48c6 RE |
285 | es->top=es->bottom=0; |
286 | } | |
287 | ||
d02b48c6 RE |
288 | |
289 | unsigned long ERR_get_error() | |
58964a49 | 290 | { return(get_error_values(1,NULL,NULL,NULL,NULL)); } |
d02b48c6 | 291 | |
58964a49 RE |
292 | unsigned long ERR_get_error_line(file,line) |
293 | char **file; | |
294 | int *line; | |
295 | { return(get_error_values(1,file,line,NULL,NULL)); } | |
d02b48c6 | 296 | |
58964a49 RE |
297 | unsigned long ERR_get_error_line_data(file,line,data,flags) |
298 | char **file; | |
299 | int *line; | |
300 | char **data; | |
301 | int *flags; | |
302 | { return(get_error_values(1,file,line,data,flags)); } | |
d02b48c6 | 303 | |
58964a49 RE |
304 | unsigned long ERR_peek_error() |
305 | { return(get_error_values(0,NULL,NULL,NULL,NULL)); } | |
d02b48c6 RE |
306 | |
307 | unsigned long ERR_peek_error_line(file,line) | |
308 | char **file; | |
309 | int *line; | |
58964a49 | 310 | { return(get_error_values(0,file,line,NULL,NULL)); } |
d02b48c6 | 311 | |
58964a49 RE |
312 | unsigned long ERR_peek_error_line_data(file,line,data,flags) |
313 | char **file; | |
314 | int *line; | |
315 | char **data; | |
316 | int *flags; | |
317 | { return(get_error_values(0,file,line,data,flags)); } | |
d02b48c6 | 318 | |
58964a49 RE |
319 | static unsigned long get_error_values(inc,file,line,data,flags) |
320 | int inc; | |
d02b48c6 RE |
321 | char **file; |
322 | int *line; | |
58964a49 RE |
323 | char **data; |
324 | int *flags; | |
325 | { | |
326 | int i=0; | |
d02b48c6 | 327 | ERR_STATE *es; |
58964a49 | 328 | unsigned long ret; |
d02b48c6 RE |
329 | |
330 | es=ERR_get_state(); | |
331 | ||
58964a49 | 332 | if (es->bottom == es->top) return(0); |
d02b48c6 | 333 | i=(es->bottom+1)%ERR_NUM_ERRORS; |
58964a49 RE |
334 | |
335 | ret=es->err_buffer[i]; | |
336 | if (inc) | |
d02b48c6 | 337 | { |
58964a49 RE |
338 | es->bottom=i; |
339 | es->err_buffer[i]=0; | |
d02b48c6 | 340 | } |
58964a49 RE |
341 | |
342 | if ((file != NULL) && (line != NULL)) | |
d02b48c6 | 343 | { |
58964a49 RE |
344 | if (es->err_file[i] == NULL) |
345 | { | |
346 | *file="NA"; | |
347 | if (line != NULL) *line=0; | |
348 | } | |
349 | else | |
350 | { | |
351 | *file=es->err_file[i]; | |
352 | if (line != NULL) *line=es->err_line[i]; | |
353 | } | |
d02b48c6 | 354 | } |
d02b48c6 | 355 | |
58964a49 RE |
356 | if (data != NULL) |
357 | { | |
358 | if (es->err_data[i] == NULL) | |
359 | { | |
360 | *data=""; | |
361 | if (flags != NULL) *flags=0; | |
362 | } | |
363 | else | |
364 | { | |
365 | *data=es->err_data[i]; | |
366 | if (flags != NULL) *flags=es->err_data_flags[i]; | |
367 | } | |
368 | } | |
d02b48c6 RE |
369 | return(ret); |
370 | } | |
371 | ||
372 | /* BAD for multi-threaded, uses a local buffer if ret == NULL */ | |
373 | char *ERR_error_string(e,ret) | |
374 | unsigned long e; | |
375 | char *ret; | |
376 | { | |
377 | static char buf[256]; | |
378 | char *ls,*fs,*rs; | |
379 | unsigned long l,f,r; | |
380 | int i; | |
381 | ||
382 | l=ERR_GET_LIB(e); | |
383 | f=ERR_GET_FUNC(e); | |
384 | r=ERR_GET_REASON(e); | |
385 | ||
386 | ls=ERR_lib_error_string(e); | |
387 | fs=ERR_func_error_string(e); | |
388 | rs=ERR_reason_error_string(e); | |
389 | ||
390 | if (ret == NULL) ret=buf; | |
391 | ||
392 | sprintf(&(ret[0]),"error:%08lX:",e); | |
393 | i=strlen(ret); | |
394 | if (ls == NULL) | |
395 | sprintf(&(ret[i]),":lib(%lu) ",l); | |
396 | else sprintf(&(ret[i]),"%s",ls); | |
397 | i=strlen(ret); | |
398 | if (fs == NULL) | |
399 | sprintf(&(ret[i]),":func(%lu) ",f); | |
400 | else sprintf(&(ret[i]),":%s",fs); | |
401 | i=strlen(ret); | |
402 | if (rs == NULL) | |
403 | sprintf(&(ret[i]),":reason(%lu)",r); | |
404 | else sprintf(&(ret[i]),":%s",rs); | |
405 | ||
406 | return(ret); | |
407 | } | |
408 | ||
409 | LHASH *ERR_get_string_table() | |
410 | { | |
411 | return(error_hash); | |
412 | } | |
413 | ||
414 | LHASH *ERR_get_err_state_table() | |
415 | { | |
416 | return(thread_hash); | |
417 | } | |
418 | ||
419 | char *ERR_lib_error_string(e) | |
420 | unsigned long e; | |
421 | { | |
422 | ERR_STRING_DATA d,*p=NULL; | |
423 | unsigned long l; | |
424 | ||
425 | l=ERR_GET_LIB(e); | |
426 | ||
427 | CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH); | |
428 | ||
429 | if (error_hash != NULL) | |
430 | { | |
431 | d.error=ERR_PACK(l,0,0); | |
432 | p=(ERR_STRING_DATA *)lh_retrieve(error_hash,(char *)&d); | |
433 | } | |
434 | ||
435 | CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); | |
436 | ||
437 | return((p == NULL)?NULL:p->string); | |
438 | } | |
439 | ||
440 | char *ERR_func_error_string(e) | |
441 | unsigned long e; | |
442 | { | |
443 | ERR_STRING_DATA d,*p=NULL; | |
444 | unsigned long l,f; | |
445 | ||
446 | l=ERR_GET_LIB(e); | |
447 | f=ERR_GET_FUNC(e); | |
448 | ||
449 | CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH); | |
450 | ||
451 | if (error_hash != NULL) | |
452 | { | |
453 | d.error=ERR_PACK(l,f,0); | |
454 | p=(ERR_STRING_DATA *)lh_retrieve(error_hash,(char *)&d); | |
455 | } | |
456 | ||
457 | CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); | |
458 | ||
459 | return((p == NULL)?NULL:p->string); | |
460 | } | |
461 | ||
462 | char *ERR_reason_error_string(e) | |
463 | unsigned long e; | |
464 | { | |
465 | ERR_STRING_DATA d,*p=NULL; | |
466 | unsigned long l,r; | |
467 | ||
468 | l=ERR_GET_LIB(e); | |
469 | r=ERR_GET_REASON(e); | |
470 | ||
471 | CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH); | |
472 | ||
473 | if (error_hash != NULL) | |
474 | { | |
475 | d.error=ERR_PACK(l,0,r); | |
476 | p=(ERR_STRING_DATA *)lh_retrieve(error_hash,(char *)&d); | |
477 | if (p == NULL) | |
478 | { | |
479 | d.error=ERR_PACK(0,0,r); | |
480 | p=(ERR_STRING_DATA *)lh_retrieve(error_hash, | |
481 | (char *)&d); | |
482 | } | |
483 | } | |
484 | ||
485 | CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH); | |
486 | ||
487 | return((p == NULL)?NULL:p->string); | |
488 | } | |
489 | ||
490 | static unsigned long err_hash(a) | |
491 | ERR_STRING_DATA *a; | |
492 | { | |
493 | unsigned long ret,l; | |
494 | ||
495 | l=a->error; | |
496 | ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l); | |
497 | return(ret^ret%19*13); | |
498 | } | |
499 | ||
500 | static int err_cmp(a,b) | |
501 | ERR_STRING_DATA *a,*b; | |
502 | { | |
503 | return((int)(a->error-b->error)); | |
504 | } | |
505 | ||
506 | static unsigned long pid_hash(a) | |
507 | ERR_STATE *a; | |
508 | { | |
509 | return(a->pid*13); | |
510 | } | |
511 | ||
512 | static int pid_cmp(a,b) | |
513 | ERR_STATE *a,*b; | |
514 | { | |
515 | return((int)((long)a->pid - (long)b->pid)); | |
516 | } | |
517 | ||
518 | void ERR_remove_state(pid) | |
519 | unsigned long pid; | |
520 | { | |
521 | ERR_STATE *p,tmp; | |
522 | ||
523 | if (thread_hash == NULL) | |
524 | return; | |
525 | if (pid == 0) | |
526 | pid=(unsigned long)CRYPTO_thread_id(); | |
527 | tmp.pid=pid; | |
528 | CRYPTO_w_lock(CRYPTO_LOCK_ERR); | |
529 | p=(ERR_STATE *)lh_delete(thread_hash,(char *)&tmp); | |
d02b48c6 | 530 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
58964a49 RE |
531 | |
532 | if (p != NULL) ERR_STATE_free(p); | |
d02b48c6 RE |
533 | } |
534 | ||
535 | ERR_STATE *ERR_get_state() | |
536 | { | |
537 | static ERR_STATE fallback; | |
538 | ERR_STATE *ret=NULL,tmp,*tmpp; | |
58964a49 | 539 | int i; |
d02b48c6 RE |
540 | unsigned long pid; |
541 | ||
542 | pid=(unsigned long)CRYPTO_thread_id(); | |
543 | ||
544 | CRYPTO_r_lock(CRYPTO_LOCK_ERR); | |
545 | if (thread_hash == NULL) | |
546 | { | |
547 | CRYPTO_r_unlock(CRYPTO_LOCK_ERR); | |
548 | CRYPTO_w_lock(CRYPTO_LOCK_ERR); | |
549 | if (thread_hash == NULL) | |
550 | { | |
dfeab068 | 551 | MemCheck_off(); |
d02b48c6 | 552 | thread_hash=lh_new(pid_hash,pid_cmp); |
dfeab068 | 553 | MemCheck_on(); |
d02b48c6 RE |
554 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
555 | if (thread_hash == NULL) return(&fallback); | |
556 | } | |
557 | else | |
558 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR); | |
559 | } | |
560 | else | |
561 | { | |
562 | tmp.pid=pid; | |
563 | ret=(ERR_STATE *)lh_retrieve(thread_hash,(char *)&tmp); | |
564 | CRYPTO_r_unlock(CRYPTO_LOCK_ERR); | |
565 | } | |
566 | ||
567 | /* ret == the error state, if NULL, make a new one */ | |
568 | if (ret == NULL) | |
569 | { | |
570 | ret=(ERR_STATE *)Malloc(sizeof(ERR_STATE)); | |
571 | if (ret == NULL) return(&fallback); | |
572 | ret->pid=pid; | |
573 | ret->top=0; | |
574 | ret->bottom=0; | |
58964a49 RE |
575 | for (i=0; i<ERR_NUM_ERRORS; i++) |
576 | { | |
577 | ret->err_data[i]=NULL; | |
578 | ret->err_data_flags[i]=0; | |
579 | } | |
d02b48c6 RE |
580 | CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
581 | tmpp=(ERR_STATE *)lh_insert(thread_hash,(char *)ret); | |
582 | CRYPTO_w_unlock(CRYPTO_LOCK_ERR); | |
583 | if (tmpp != NULL) /* old entry - should not happen */ | |
58964a49 RE |
584 | { |
585 | ERR_STATE_free(tmpp); | |
586 | } | |
d02b48c6 RE |
587 | } |
588 | return(ret); | |
589 | } | |
590 | ||
58964a49 RE |
591 | int ERR_get_next_error_library() |
592 | { | |
593 | static int value=ERR_LIB_USER; | |
594 | ||
595 | return(value++); | |
596 | } | |
597 | ||
598 | void ERR_set_error_data(data,flags) | |
599 | char *data; | |
600 | int flags; | |
601 | { | |
602 | ERR_STATE *es; | |
603 | int i; | |
604 | ||
605 | es=ERR_get_state(); | |
606 | ||
607 | i=es->top; | |
608 | if (i == 0) | |
609 | i=ERR_NUM_ERRORS-1; | |
610 | ||
611 | es->err_data[i]=data; | |
612 | es->err_data_flags[es->top]=flags; | |
613 | } | |
614 | ||
615 | void ERR_add_error_data( VAR_PLIST(int , num)) | |
616 | VAR_ALIST | |
617 | { | |
618 | VAR_BDEFN(args, int, num); | |
619 | int i,n,s; | |
620 | char *str,*p,*a; | |
621 | ||
622 | s=64; | |
623 | str=Malloc(s+1); | |
624 | if (str == NULL) return; | |
625 | str[0]='\0'; | |
626 | ||
627 | VAR_INIT(args,int,num); | |
628 | n=0; | |
629 | for (i=0; i<num; i++) | |
630 | { | |
631 | VAR_ARG(args,char *,a); | |
dfeab068 RE |
632 | /* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */ |
633 | if (a != NULL) | |
58964a49 | 634 | { |
dfeab068 RE |
635 | n+=strlen(a); |
636 | if (n > s) | |
58964a49 | 637 | { |
dfeab068 RE |
638 | s=n+20; |
639 | p=Realloc(str,s+1); | |
640 | if (p == NULL) | |
641 | { | |
642 | Free(str); | |
643 | return; | |
644 | } | |
645 | else | |
646 | str=p; | |
58964a49 | 647 | } |
dfeab068 | 648 | strcat(str,a); |
58964a49 | 649 | } |
58964a49 RE |
650 | } |
651 | ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING); | |
652 | ||
653 | VAR_END( args ); | |
654 | } | |
655 |