diff options
author | Ken Raeburn <raeburn@mit.edu> | 2006-03-26 20:55:59 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@mit.edu> | 2006-03-26 20:55:59 +0000 |
commit | b5a541c640dfedda7480332f4838e30f0a9e1770 (patch) | |
tree | b5182550f1c3fb475c3b71d15f4944fbcc16c4bb /src/util/support/errors.c | |
parent | 976289e5db9426efb6aa56cf0c97b89b4e30d1b4 (diff) | |
download | krb5-b5a541c640dfedda7480332f4838e30f0a9e1770.tar.gz krb5-b5a541c640dfedda7480332f4838e30f0a9e1770.tar.xz krb5-b5a541c640dfedda7480332f4838e30f0a9e1770.zip |
Initial enhanced error message support, similar to what I sent to
krbdev except for some function renaming (krb5_free_error was already
in use, so added _message to everything), and the context is allowed
to be NULL (in which case we fall back to error_message() and storing
no strings) to simplify some code.
Low-level routines in the support library, using a private data
structure; higher-level routines in libkrb5, using a krb5_context.
Added error info strings to the KRB_ERR_GENERIC case in gc_via_tkt.c
and the python sample service location plugin. Added code to kinit
and kvno to look up and display the strings.
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17776 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/util/support/errors.c')
-rw-r--r-- | src/util/support/errors.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/util/support/errors.c b/src/util/support/errors.c new file mode 100644 index 000000000..185cb425a --- /dev/null +++ b/src/util/support/errors.c @@ -0,0 +1,134 @@ +/* Can't include krb5.h here, or k5-int.h which includes it, because + krb5.h needs to be generated with error tables, after util/et, + which builds after this directory. */ +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "k5-err.h" + +#include "k5-thread.h" +#include "k5-platform.h" + +/* It would be nice to just use error_message() always. Pity that + it's defined in a library that depends on this one, and we're not + allowed to make circular dependencies. */ +/* We really want a rwlock here, since we should hold it while calling + the function and copying out its results. But I haven't + implemented shims for rwlock yet. */ +static k5_mutex_t krb5int_error_info_support_mutex = + K5_MUTEX_PARTIAL_INITIALIZER; +static const char *(KRB5_CALLCONV *fptr)(long); /* = &error_message */ + +int +krb5int_err_init (void) +{ + return k5_mutex_finish_init (&krb5int_error_info_support_mutex); +} +#define initialize() krb5int_call_thread_support_init() +#define lock() k5_mutex_lock(&krb5int_error_info_support_mutex) +#define unlock() k5_mutex_unlock(&krb5int_error_info_support_mutex) + +void +krb5int_set_error (struct errinfo *ep, long code, const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + krb5int_vset_error (ep, code, fmt, args); + va_end (args); +} + +void +krb5int_vset_error (struct errinfo *ep, long code, + const char *fmt, va_list args) +{ + if (ep->msg && ep->msg != ep->scratch_buf) { + free (ep->msg); + ep->msg = NULL; + } + ep->code = code; +#ifdef HAVE_VASPRINTF + { + char *str = NULL; + if (vasprintf(&str, fmt, args) >= 0 && str != NULL) { + ep->msg = str; + return; + } + } +#endif + vsnprintf(ep->scratch_buf, sizeof(ep->scratch_buf), fmt, args); + ep->msg = ep->scratch_buf; +} + +char * +krb5int_get_error (struct errinfo *ep, long code) +{ + char *r, *r2; + if (code != ep->code) + krb5int_clear_error (ep); + if (ep->msg) { + r = ep->msg; + ep->msg = NULL; + return r; + } + if (initialize() != 0) { + strncpy(ep->scratch_buf, _("Kerberos library initialization failure"), + sizeof(ep->scratch_buf)); + ep->scratch_buf[sizeof(ep->scratch_buf)-1] = 0; + ep->msg = NULL; + return ep->scratch_buf; + } + lock(); + if (fptr == NULL) { + unlock(); + r = strerror (code); + if (r) { + if (strlen (r) < sizeof (ep->scratch_buf) + || (r2 = strdup (r)) == NULL) { + strncpy (ep->scratch_buf, r, sizeof(ep->scratch_buf)); + return ep->scratch_buf; + } else + return r2; + } + format_number: + sprintf (ep->scratch_buf, _("error %ld"), code); + return ep->scratch_buf; + } + r = fptr(code); + if (r == NULL) { + unlock(); + goto format_number; + } + r2 = strdup (r); + if (r2 == NULL) { + strncpy(ep->scratch_buf, r, sizeof(ep->scratch_buf)); + unlock(); + return ep->scratch_buf; + } else { + unlock(); + return r2; + } +} + +void +krb5int_free_error (struct errinfo *ep, char *msg) +{ + if (msg != ep->scratch_buf) + free (msg); +} + +void +krb5int_clear_error (struct errinfo *ep) +{ + krb5int_free_error (ep, ep->msg); + ep->msg = NULL; +} + +void +krb5int_set_error_info_callout_fn (const char *(KRB5_CALLCONV *f)(long)) +{ + initialize(); + lock(); + fptr = f; + unlock(); +} |