summaryrefslogtreecommitdiffstats
path: root/src/util/support/errors.c
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2006-03-26 20:55:59 +0000
committerKen Raeburn <raeburn@mit.edu>2006-03-26 20:55:59 +0000
commitb5a541c640dfedda7480332f4838e30f0a9e1770 (patch)
treeb5182550f1c3fb475c3b71d15f4944fbcc16c4bb /src/util/support/errors.c
parent976289e5db9426efb6aa56cf0c97b89b4e30d1b4 (diff)
downloadkrb5-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.c134
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();
+}