Error handling cleanup 3.
[radsecproxy.git] / lib / err.c
1 /* See the file COPYING for licensing information.  */
2
3 #if defined HAVE_CONFIG_H
4 #include <config.h>
5 #endif
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <assert.h>
10 #include <radsec/radsec.h>
11 #include <radsec/radsec-impl.h>
12
13 static const char *_errtxt[] = {
14   "SUCCESS",                    /* 0 RSE_OK */
15   "out of memory",              /* 1 RSE_NOMEM */
16   "not yet implemented",        /* 2 RSE_NOSYS */
17   "invalid handle",             /* 3 RSE_INVALID_CTX */
18   "invalid connection",         /* 4 RSE_INVALID_CONN */
19   "connection type mismatch",   /* 5 RSE_CONN_TYPE_MISMATCH */
20   "FreeRadius error",           /* 6 RSE_FR */
21   "bad hostname or port",       /* 7 RSE_BADADDR */
22   "no peer configured",         /* 8 RSE_NOPEER */
23   "libevent error",             /* 9 RSE_EVENT */
24   "socket error",               /* 10 RSE_SOCKERR */
25   "invalid configuration file", /* 11 RSE_CONFIG */
26   "authentication failed",      /* 12 RSE_BADAUTH */
27   "internal error",             /* 13 RSE_INTERNAL */
28   "SSL error",                  /* 14 RSE_SSLERR */
29   "invalid packet",             /* 15 RSE_INVALID_PKT */
30   "connect timeout",            /* 16 RSE_TIMEOUT_CONN */
31   "invalid argument",           /* 17 RSE_INVAL */
32   "I/O timeout",                /* 18 RSE_TIMEOUT_IO */
33 };
34 #define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt))
35
36 static struct rs_error *
37 _err_vcreate (unsigned int code, const char *file, int line, const char *fmt,
38               va_list args)
39 {
40   struct rs_error *err;
41
42   err = malloc (sizeof(struct rs_error));
43   if (err)
44     {
45       int n;
46       memset (err, 0, sizeof(struct rs_error));
47       err->code = code;
48       if (fmt)
49         n = vsnprintf (err->buf, sizeof(err->buf), fmt, args);
50       else
51         {
52           strncpy (err->buf,
53                    err->code < ERRTXT_SIZE ? _errtxt[err->code] : "",
54                    sizeof(err->buf));
55           n = strlen (err->buf);
56         }
57       if (n >= 0 && file)
58         {
59           char *sep = strrchr (file, '/');
60           if (sep)
61             file = sep + 1;
62           snprintf (err->buf + n, sizeof(err->buf) - n, " (%s:%d)", file,
63                     line);
64         }
65     }
66   return err;
67 }
68
69 struct rs_error *
70 _rs_err_create (unsigned int code, const char *file, int line, const char *fmt,
71                 ...)
72 {
73   struct rs_error *err;
74
75   va_list args;
76   va_start (args, fmt);
77   err = _err_vcreate (code, file, line, fmt, args);
78   va_end (args);
79   return err;
80 }
81
82 static int
83 _ctx_err_vpush_fl (struct rs_context *ctx, int code, const char *file,
84                    int line, const char *fmt, va_list args)
85 {
86   struct rs_error *err = _err_vcreate (code, file, line, fmt, args);
87
88   if (err)
89     ctx->err = err;
90   return code;
91 }
92
93 int
94 rs_err_ctx_push (struct rs_context *ctx, int code, const char *fmt, ...)
95 {
96   va_list args;
97   va_start (args, fmt);
98   _ctx_err_vpush_fl (ctx, code, NULL, 0, fmt, args);
99   va_end (args);
100   return code;
101 }
102
103 int
104 rs_err_ctx_push_fl (struct rs_context *ctx, int code, const char *file,
105                     int line, const char *fmt, ...)
106 {
107   va_list args;
108   va_start (args, fmt);
109   _ctx_err_vpush_fl (ctx, code, file, line, fmt, args);
110   va_end (args);
111   return code;
112 }
113
114 int
115 _rs_err_conn_push_err (struct rs_connection *conn, struct rs_error *err)
116 {
117   conn->err = err;              /* FIXME: use a stack */
118   return err->code;
119 }
120
121 static int
122 _conn_err_vpush_fl (struct rs_connection *conn, int code, const char *file,
123                     int line, const char *fmt, va_list args)
124 {
125   struct rs_error *err = _err_vcreate (code, file, line, fmt, args);
126
127   if (err)
128     _rs_err_conn_push_err (conn, err);
129   return code;
130 }
131
132 int
133 rs_err_conn_push (struct rs_connection *conn, int code, const char *fmt, ...)
134 {
135   va_list args;
136   va_start (args, fmt);
137   _conn_err_vpush_fl (conn, code, NULL, 0, fmt, args);
138   va_end (args);
139   return code;
140 }
141
142 int
143 rs_err_conn_push_fl (struct rs_connection *conn, int code, const char *file,
144                      int line, const char *fmt, ...)
145 {
146   va_list args;
147   va_start (args, fmt);
148   _conn_err_vpush_fl (conn, code, file, line, fmt, args);
149   va_end (args);
150   return code;
151 }
152
153 struct rs_error *
154 rs_err_ctx_pop (struct rs_context *ctx)
155 {
156   struct rs_error *err;
157
158   if (!ctx)
159     return NULL;                /* FIXME: RSE_INVALID_CTX.  */
160   err = ctx->err;
161   ctx->err = NULL;
162   return err;
163 }
164
165 struct rs_error *
166 rs_err_conn_pop (struct rs_connection *conn)
167 {
168   struct rs_error *err;
169
170   if (!conn)
171     return NULL;                /* FIXME: RSE_INVALID_CONN */
172   err = conn->err;
173   conn->err = NULL;
174   return err;
175 }
176
177 int
178 rs_err_conn_peek_code (struct rs_connection *conn)
179 {
180   if (conn && conn->err)
181     return conn->err->code;
182   else
183     return RSE_OK;
184 }
185
186 void
187 rs_err_free (struct rs_error *err)
188 {
189   assert (err);
190   if (err->msg)
191     free (err->msg);
192   free (err);
193 }
194
195 char *
196 rs_err_msg (struct rs_error *err, int dofree_flag)
197 {
198   char *msg;
199
200   if (!err)
201     return NULL;
202   if (err->msg)
203     msg = err->msg;
204   else
205     msg = strdup (err->buf);
206
207   if (dofree_flag)
208     rs_err_free (err);
209   return msg;
210 }
211
212 int
213 rs_err_code (struct rs_error *err, int dofree_flag)
214 {
215   int code;
216
217   if (!err)
218     return -1;
219   code = err->code;
220
221   if (dofree_flag)
222     rs_err_free(err);
223   return code;
224 }