]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/err/err.c
Fix DH key generation.
[thirdparty/openssl.git] / crypto / err / err.c
CommitLineData
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
68static LHASH *error_hash=NULL;
69static LHASH *thread_hash=NULL;
70
71#ifndef NOPROTO
72static unsigned long err_hash(ERR_STRING_DATA *a);
73static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b);
74static unsigned long pid_hash(ERR_STATE *pid);
75static int pid_cmp(ERR_STATE *a,ERR_STATE *pid);
58964a49
RE
76static unsigned long get_error_values(int inc,char **file,int *line,
77 char **data,int *flags);
78static void ERR_STATE_free(ERR_STATE *s);
d02b48c6
RE
79#else
80static unsigned long err_hash();
81static int err_cmp();
82static unsigned long pid_hash();
83static int pid_cmp();
dfeab068 84static unsigned long get_error_values();
58964a49
RE
85static void ERR_STATE_free();
86ERR_STATE *s;
d02b48c6
RE
87#endif
88
89#ifndef NO_ERR
90static 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
114static 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
130static 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
173static void ERR_STATE_free(s)
174ERR_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
185void 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
208void ERR_load_strings(lib,str)
209int lib;
210ERR_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
236void 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
251void ERR_put_error(lib,func,reason,file,line)
252int lib,func,reason;
253char *file;
254int 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
269void 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
289unsigned long ERR_get_error()
58964a49 290 { return(get_error_values(1,NULL,NULL,NULL,NULL)); }
d02b48c6 291
58964a49
RE
292unsigned long ERR_get_error_line(file,line)
293char **file;
294int *line;
295 { return(get_error_values(1,file,line,NULL,NULL)); }
d02b48c6 296
58964a49
RE
297unsigned long ERR_get_error_line_data(file,line,data,flags)
298char **file;
299int *line;
300char **data;
301int *flags;
302 { return(get_error_values(1,file,line,data,flags)); }
d02b48c6 303
58964a49
RE
304unsigned long ERR_peek_error()
305 { return(get_error_values(0,NULL,NULL,NULL,NULL)); }
d02b48c6
RE
306
307unsigned long ERR_peek_error_line(file,line)
308char **file;
309int *line;
58964a49 310 { return(get_error_values(0,file,line,NULL,NULL)); }
d02b48c6 311
58964a49
RE
312unsigned long ERR_peek_error_line_data(file,line,data,flags)
313char **file;
314int *line;
315char **data;
316int *flags;
317 { return(get_error_values(0,file,line,data,flags)); }
d02b48c6 318
58964a49
RE
319static unsigned long get_error_values(inc,file,line,data,flags)
320int inc;
d02b48c6
RE
321char **file;
322int *line;
58964a49
RE
323char **data;
324int *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 */
373char *ERR_error_string(e,ret)
374unsigned long e;
375char *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
409LHASH *ERR_get_string_table()
410 {
411 return(error_hash);
412 }
413
414LHASH *ERR_get_err_state_table()
415 {
416 return(thread_hash);
417 }
418
419char *ERR_lib_error_string(e)
420unsigned 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
440char *ERR_func_error_string(e)
441unsigned 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
462char *ERR_reason_error_string(e)
463unsigned 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
490static unsigned long err_hash(a)
491ERR_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
500static int err_cmp(a,b)
501ERR_STRING_DATA *a,*b;
502 {
503 return((int)(a->error-b->error));
504 }
505
506static unsigned long pid_hash(a)
507ERR_STATE *a;
508 {
509 return(a->pid*13);
510 }
511
512static int pid_cmp(a,b)
513ERR_STATE *a,*b;
514 {
515 return((int)((long)a->pid - (long)b->pid));
516 }
517
518void ERR_remove_state(pid)
519unsigned 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
535ERR_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
591int ERR_get_next_error_library()
592 {
593 static int value=ERR_LIB_USER;
594
595 return(value++);
596 }
597
598void ERR_set_error_data(data,flags)
599char *data;
600int 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
615void ERR_add_error_data( VAR_PLIST(int , num))
616VAR_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