237d346f4dcda072da7673130604066bbea7956b
[kai/samba.git] / source4 / heimdal / lib / krb5 / error_string.c
1 /*
2  * Copyright (c) 2001, 2003, 2005 - 2006 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include "krb5_locl.h"
35
36 #undef __attribute__
37 #define __attribute__(x)
38
39 /**
40  * Clears the error message from the Kerberos 5 context.
41  *
42  * @param context The Kerberos 5 context to clear
43  *
44  * @ingroup krb5_error
45  */
46
47 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
48 krb5_clear_error_message(krb5_context context)
49 {
50     HEIMDAL_MUTEX_lock(context->mutex);
51     if (context->error_string)
52         free(context->error_string);
53     context->error_code = 0;
54     context->error_string = NULL;
55     HEIMDAL_MUTEX_unlock(context->mutex);
56 }
57
58 /**
59  * Set the context full error string for a specific error code.
60  * The error that is stored should be internationalized.
61  *
62  * @param context Kerberos 5 context
63  * @param ret The error code
64  * @param fmt Error string for the error code
65  * @param ... printf(3) style parameters.
66  *
67  * @ingroup krb5_error
68  */
69
70 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
71 krb5_set_error_message(krb5_context context, krb5_error_code ret,
72                        const char *fmt, ...)
73     __attribute__ ((format (printf, 3, 4)))
74 {
75     va_list ap;
76
77     va_start(ap, fmt);
78     krb5_vset_error_message (context, ret, fmt, ap);
79     va_end(ap);
80 }
81
82 /**
83  * Set the context full error string for a specific error code.
84  *
85  * @param context Kerberos 5 context
86  * @param ret The error code
87  * @param fmt Error string for the error code
88  * @param args printf(3) style parameters.
89  *
90  * @ingroup krb5_error
91  */
92
93
94 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
95 krb5_vset_error_message (krb5_context context, krb5_error_code ret,
96                          const char *fmt, va_list args)
97     __attribute__ ((format (printf, 3, 0)))
98 {
99     int r;
100
101     HEIMDAL_MUTEX_lock(context->mutex);
102     if (context->error_string) {
103         free(context->error_string);
104         context->error_string = NULL;
105     }
106     context->error_code = ret;
107     r = vasprintf(&context->error_string, fmt, args);
108     if (r < 0)
109         context->error_string = NULL;
110     HEIMDAL_MUTEX_unlock(context->mutex);
111 }
112
113 /**
114  * Prepend the context full error string for a specific error code.
115  * The error that is stored should be internationalized.
116  *
117  * @param context Kerberos 5 context
118  * @param ret The error code
119  * @param fmt Error string for the error code
120  * @param ... printf(3) style parameters.
121  *
122  * @ingroup krb5_error
123  */
124
125 void KRB5_LIB_FUNCTION
126 krb5_prepend_error_message(krb5_context context, krb5_error_code ret,
127                            const char *fmt, ...)
128     __attribute__ ((format (printf, 3, 4)))
129 {
130     va_list ap;
131
132     va_start(ap, fmt);
133     krb5_vprepend_error_message(context, ret, fmt, ap);
134     va_end(ap);
135 }
136
137 /**
138  * Prepend the contexts's full error string for a specific error code.
139  *
140  * @param context Kerberos 5 context
141  * @param ret The error code
142  * @param fmt Error string for the error code
143  * @param args printf(3) style parameters.
144  *
145  * @ingroup krb5_error
146  */
147
148 void KRB5_LIB_FUNCTION
149 krb5_vprepend_error_message(krb5_context context, krb5_error_code ret,
150                             const char *fmt, va_list args)
151     __attribute__ ((format (printf, 3, 0)))
152 {
153     char *str = NULL, *str2 = NULL;
154     HEIMDAL_MUTEX_lock(context->mutex);
155     if (context->error_code != ret) {
156         HEIMDAL_MUTEX_unlock(context->mutex);
157         return;
158     }
159     if (vasprintf(&str, fmt, args) < 0 || str == NULL) {
160         HEIMDAL_MUTEX_unlock(context->mutex);
161         return;
162     }
163     if (context->error_string) {
164         int e;
165
166         e = asprintf(&str2, "%s: %s", str, context->error_string);
167         free(context->error_string);
168         if (e < 0 || str2 == NULL)
169             context->error_string = NULL;
170         else
171             context->error_string = str2;
172         free(str);
173     } else
174         context->error_string = str;
175     HEIMDAL_MUTEX_unlock(context->mutex);
176 }
177
178
179 /**
180  * Return the error message in context. On error or no error string,
181  * the function returns NULL.
182  *
183  * @param context Kerberos 5 context
184  *
185  * @return an error string, needs to be freed with
186  * krb5_free_error_message(). The functions return NULL on error.
187  *
188  * @ingroup krb5_error
189  */
190
191 KRB5_LIB_FUNCTION char * KRB5_LIB_CALL
192 krb5_get_error_string(krb5_context context)
193 {
194     char *ret = NULL;
195
196     HEIMDAL_MUTEX_lock(context->mutex);
197     if (context->error_string)
198         ret = strdup(context->error_string);
199     HEIMDAL_MUTEX_unlock(context->mutex);
200     return ret;
201 }
202
203 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
204 krb5_have_error_string(krb5_context context)
205 {
206     char *str;
207     HEIMDAL_MUTEX_lock(context->mutex);
208     str = context->error_string;
209     HEIMDAL_MUTEX_unlock(context->mutex);
210     return str != NULL;
211 }
212
213 /**
214  * Return the error message for `code' in context. On memory
215  * allocation error the function returns NULL.
216  *
217  * @param context Kerberos 5 context
218  * @param code Error code related to the error
219  *
220  * @return an error string, needs to be freed with
221  * krb5_free_error_message(). The functions return NULL on error.
222  *
223  * @ingroup krb5_error
224  */
225
226 KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
227 krb5_get_error_message(krb5_context context, krb5_error_code code)
228 {
229     char *str;
230
231     HEIMDAL_MUTEX_lock(context->mutex);
232     if (context->error_string &&
233         (code == context->error_code || context->error_code == 0))
234     {
235         str = strdup(context->error_string);
236         if (str) {
237             HEIMDAL_MUTEX_unlock(context->mutex);
238             return str;
239         }
240     }
241     HEIMDAL_MUTEX_unlock(context->mutex);
242
243     if (code == 0)
244         return strdup("Success");
245     {
246         const char *msg;
247         char buf[128];
248         msg = com_right_r(context->et_list, code, buf, sizeof(buf));
249         if (msg)
250             return strdup(msg);
251     }
252
253     if (asprintf(&str, "<unknown error: %d>", (int)code) == -1 || str == NULL)
254         return NULL;
255
256     return str;
257 }
258
259
260 /**
261  * Free the error message returned by krb5_get_error_message().
262  *
263  * @param context Kerberos context
264  * @param msg error message to free, returned byg
265  *        krb5_get_error_message().
266  *
267  * @ingroup krb5_error
268  */
269
270 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
271 krb5_free_error_message(krb5_context context, const char *msg)
272 {
273     free(rk_UNCONST(msg));
274 }
275
276
277 /**
278  * Return the error string for the error code. The caller must not
279  * free the string.
280  *
281  * This function is deprecated since its not threadsafe.
282  *
283  * @param context Kerberos 5 context.
284  * @param code Kerberos error code.
285  *
286  * @return the error message matching code
287  *
288  * @ingroup krb5
289  */
290
291 KRB5_DEPRECATED
292 KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
293 krb5_get_err_text(krb5_context context, krb5_error_code code)
294 {
295     const char *p = NULL;
296     if(context != NULL)
297         p = com_right(context->et_list, code);
298     if(p == NULL)
299         p = strerror(code);
300     if (p == NULL)
301         p = "Unknown error";
302     return p;
303 }