WIP.
[libradsec.git] / lib / err.c
1 /* See the file COPYING for licensing information.  */
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <radsec/radsec.h>
7 #include <radsec/radsec-impl.h>
8
9 const char *_errtxt[] = {
10   "SUCCESS",                    /* 0 RSE_OK */
11   "NOMEM",                      /* 1 RSE_NOMEM */
12   "NYI -- not yet implemented", /* 2 RSE_NOSYS */
13   "invalid handle"              /* 3 RSE_INVALID_CTX */
14   "invalid connection"          /* 4 RSE_INVALID_CONN */
15   "connection type mismatch"    /* 5 RSE_CONN_TYPE_MISMATCH */
16   "FreeRadius error"            /* 6 RSE_FR */
17   "bad hostname or port"        /* 7 RSE_BADADDR */
18   "no peer configured"          /* 8 RSE_NOPEER */
19   "libevent error"              /* 9 RSE_EVENT */
20   "connection error"            /* 10 RSE_CONNERR */
21   "ERR 11"                      /*  RSE_ */
22   "ERR 12"                      /*  RSE_ */
23   "ERR 13"                      /*  RSE_ */
24   "ERR "                        /*  RSE_ */
25   "ERR "                        /*  RSE_ */
26   "ERR "                        /*  RSE_ */
27   "ERR "                        /*  RSE_ */
28   "ERR "                        /*  RSE_ */
29   "ERR "                        /*  RSE_ */
30   "ERR "                        /*  RSE_ */
31   "some error"                  /* 21 RSE_SOME_ERROR */
32 };
33 #define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt))
34
35 static struct rs_error *
36 _err_new (unsigned int code, const char *file, int line, const char *fmt, va_list args)
37 {
38   struct rs_error *err;
39
40   err = malloc (sizeof(struct rs_error));
41   if (err)
42     {
43       int n;
44       memset (err, 0, sizeof(struct rs_error));
45       err->code = code;
46       if (fmt)
47         n = vsnprintf (err->buf, sizeof(err->buf), fmt, args);
48       else
49         {
50           strncpy (err->buf,
51                    err->code < ERRTXT_SIZE ? _errtxt[err->code] : "",
52                    sizeof(err->buf));
53           n = strlen (err->buf);
54         }
55       if (n >= 0 && file)
56         {
57           char *sep = strrchr (file, '/');
58           if (sep)
59             file = sep + 1;
60           snprintf (err->buf + n, sizeof(err->buf) - n, " (%s: %d)", file,
61                     line);
62         }
63     }
64   return err;
65 }
66
67 static int
68 _ctx_err_vpush_fl (struct rs_handle *ctx, int code, const char *file, int line, const char *fmt, va_list args)
69 {
70   struct rs_error *err = _err_new (code, file, line, fmt, args);
71
72   if (err)
73     ctx->err = err;
74   return code;
75 }
76
77 int
78 rs_ctx_err_push (struct rs_handle *ctx, int code, const char *fmt, ...)
79 {
80   va_list args;
81   va_start (args, fmt);
82   _ctx_err_vpush_fl (ctx, code, NULL, 0, fmt, args);
83   va_end (args);
84   return code;
85 }
86
87 int
88 rs_ctx_err_push_fl (struct rs_handle *ctx, int code, const char *file, int line, const char *fmt, ...)
89 {
90   va_list args;
91   va_start (args, fmt);
92   _ctx_err_vpush_fl (ctx, code, file, line, fmt, args);
93   va_end (args);
94   return code;
95 }
96
97 static int
98 _conn_err_vpush_fl (struct rs_connection *conn, int code, const char *file, int line, const char *fmt, va_list args)
99 {
100   struct rs_error *err = _err_new (code, file, line, fmt, args);
101
102   if (err)
103     conn->err = err;
104   return code;
105 }
106
107 int
108 rs_conn_err_push (struct rs_connection *conn, int code, const char *fmt, ...)
109 {
110   va_list args;
111   va_start (args, fmt);
112   _conn_err_vpush_fl (conn, code, NULL, 0, fmt, args);
113   va_end (args);
114   return code;
115 }
116
117 int
118 rs_conn_err_push_fl (struct rs_connection *conn, int code, const char *file, int line, const char *fmt, ...)
119 {
120   va_list args;
121   va_start (args, fmt);
122   _conn_err_vpush_fl (conn, code, file, line, fmt, args);
123   va_end (args);
124   return code;
125 }
126
127 struct rs_error *
128 rs_ctx_err_pop (struct rs_handle *ctx)
129 {
130   struct rs_error *err;
131
132   if (!ctx)
133     return NULL;                /* FIXME: RSE_INVALID_CTX.  */
134   err = ctx->err;
135   ctx->err = NULL;
136   return err;
137 }
138
139 struct rs_error *
140 rs_conn_err_pop (struct rs_connection *conn)
141 {
142   struct rs_error *err;
143
144   if (!conn)
145     return NULL;                /* FIXME: RSE_INVALID_CONN */
146   err = conn->err;
147   conn->err = NULL;
148   return err;
149 }
150
151 void
152 rs_err_free (struct rs_error *err)
153 {
154   assert (err);
155   if (err->msg)
156     free (err->msg);
157   free (err);
158 }
159
160 char *
161 rs_err_msg (struct rs_error *err, int dofree_flag)
162 {
163   char *msg;
164
165   if (!err)
166     return NULL;
167   if (err->msg)
168     msg = err->msg;
169   else
170     msg = strdup (err->buf);
171
172   if (dofree_flag)
173     rs_err_free (err);
174   return msg;
175 }
176
177 int
178 rs_err_code (struct rs_error *err, int dofree_flag)
179 {
180   int code;
181
182   if (!err)
183     return -1;
184   code = err->code;
185
186   if (dofree_flag)
187     rs_err_free(err);
188   return code;
189 }