1 /*****************************************************************************
2  * RRDtool 1.2.30  Copyright by Tobi Oetiker, 1997-2009
3  *****************************************************************************
4  * rrd_error.c   Common Header File
5  *****************************************************************************
6  * $Id: rrd_error.c 1735 2009-01-19 14:29:11Z oetiker $
7  * $Log$
8  * Revision 1.4  2003/02/22 21:57:03  oetiker
9  * a patch to avoid a memory leak and a Makefile.am patch to
10  * distribute all required source files -- Peter Stamfest <peter@stamfest.at>
11  *
12  * Revision 1.3  2003/02/13 07:05:27  oetiker
13  * Find attached the patch I promised to send to you. Please note that there
14  * are three new source files (src/rrd_is_thread_safe.h, src/rrd_thread_safe.c
15  * and src/rrd_not_thread_safe.c) and the introduction of librrd_th. This
16  * library is identical to librrd, but it contains support code for per-thread
17  * global variables currently used for error information only. This is similar
18  * to how errno per-thread variables are implemented.  librrd_th must be linked
19  * alongside of libpthred
20  *
21  * There is also a new file "THREADS", holding some documentation.
22  *
23  * -- Peter Stamfest <peter@stamfest.at>
24  *
25  * Revision 1.2  2002/02/01 20:34:49  oetiker
26  * fixed version number and date/time
27  *
28  * Revision 1.1.1.1  2001/02/25 22:25:05  oetiker
29  * checkin
30  *
31  *************************************************************************** */
32 
33 #include "rrd_tool.h"
34 #include <stdarg.h>
35 
36 #define MAXLEN 4096
37 #define ERRBUFLEN 256
38 #define CTX (rrd_get_context())
39 
40 void
rrd_set_error(char * fmt,...)41 rrd_set_error(char *fmt, ...)
42 {
43     va_list argp;
44     rrd_clear_error();
45     va_start(argp, fmt);
46 #ifdef HAVE_VSNPRINTF
47     vsnprintf(CTX->rrd_error, CTX->len, fmt, argp);
48 #else
49     vsprintf(CTX->rrd_error, fmt, argp);
50 #endif
51     va_end(argp);
52 }
53 
54 int
rrd_test_error(void)55 rrd_test_error(void) {
56     return CTX->rrd_error[0] != '\0';
57 }
58 
59 void
rrd_clear_error(void)60 rrd_clear_error(void){
61     CTX->rrd_error[0] = '\0';
62 }
63 
64 char *
rrd_get_error(void)65 rrd_get_error(void){
66     return CTX->rrd_error;
67 }
68 
69 #if 0
70 /* PS: Keep this stuff around, maybe we want it again if we use
71    rrd_contexts to really associate them with single RRD files and
72    operations on them... Then a single thread may use more than one
73    context. Using these functions would require to change each and
74    every function containing any of the non _r versions... */
75 void
76 rrd_set_error_r(struct rrd_context *rrd_ctx, char *fmt, ...)
77 {
78     va_list argp;
79     rrd_clear_error_r(rrd_ctx);
80     va_start(argp, fmt);
81 #ifdef HAVE_VSNPRINTF
82     vsnprintf((char *)rrd_ctx->rrd_error, rrd_ctx->len, fmt, argp);
83     rrd_ctx->rrd_error[rrd_ctx->len]='\0';
84 #else
85     vsprintf((char *)rrd_ctx->rrd_error, fmt, argp);
86 #endif
87     va_end(argp);
88 }
89 
90 int
91 rrd_test_error_r(struct rrd_context *rrd_ctx) {
92     return rrd_ctx->rrd_error[0] != '\0';
93 }
94 
95 void
96 rrd_clear_error_r(struct rrd_context *rrd_ctx) {
97     rrd_ctx->rrd_error[0] = '\0';
98 }
99 
100 char *
101 rrd_get_error_r(struct rrd_context *rrd_ctx) {
102     return (char *)rrd_ctx->rrd_error;
103 }
104 #endif
105 
106 /* PS: Should we move this to some other file? It is not really error
107    related. */
108 struct rrd_context *
rrd_new_context(void)109 rrd_new_context(void) {
110     struct rrd_context *rrd_ctx =
111 	(struct rrd_context *) malloc(sizeof(struct rrd_context));
112 
113     if (rrd_ctx) {
114 	rrd_ctx->rrd_error = malloc(MAXLEN+10);
115 	rrd_ctx->lib_errstr = malloc(ERRBUFLEN+10);
116 	if (rrd_ctx->rrd_error && rrd_ctx->lib_errstr) {
117 	    *rrd_ctx->rrd_error = 0;
118 	    *rrd_ctx->lib_errstr = 0;
119 	    rrd_ctx->len = MAXLEN;
120 	    rrd_ctx->errlen = ERRBUFLEN;
121 	    return rrd_ctx;
122 	}
123 	if (rrd_ctx->rrd_error) free(rrd_ctx->rrd_error);
124 	if (rrd_ctx->lib_errstr) free(rrd_ctx->lib_errstr);
125 	free(rrd_ctx);
126     }
127     return NULL;
128 }
129 
130 void
rrd_free_context(struct rrd_context * rrd_ctx)131 rrd_free_context(struct rrd_context *rrd_ctx) {
132     if (rrd_ctx) {
133 	if (rrd_ctx->rrd_error) free(rrd_ctx->rrd_error);
134 	if (rrd_ctx->lib_errstr) free(rrd_ctx->lib_errstr);
135 	free(rrd_ctx);
136     }
137 }
138 
139 #if 0
140 void rrd_globalize_error(struct rrd_context *rrd_ctx) {
141     if (rrd_ctx) {
142 	rrd_set_error(rrd_ctx->rrd_error);
143     }
144 }
145 #endif
146