summaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/clients/kinit/ChangeLog8
-rw-r--r--src/clients/kinit/kinit.c16
-rw-r--r--src/clients/kvno/ChangeLog8
-rw-r--r--src/clients/kvno/kvno.c34
-rw-r--r--src/include/ChangeLog9
-rw-r--r--src/include/k5-err.h23
-rw-r--r--src/include/k5-int.h6
-rw-r--r--src/include/krb5.hin15
-rw-r--r--src/lib/krb5/ChangeLog7
-rw-r--r--src/lib/krb5/krb/ChangeLog8
-rw-r--r--src/lib/krb5/krb/Makefile.in5
-rw-r--r--src/lib/krb5/krb/gc_via_tkt.c27
-rw-r--r--src/lib/krb5/krb/kerrs.c48
-rw-r--r--src/lib/krb5/krb5_libinit.c4
-rw-r--r--src/lib/krb5/libkrb5.exports5
-rw-r--r--src/plugins/locate/python/ChangeLog8
-rw-r--r--src/plugins/locate/python/Makefile.in11
-rw-r--r--src/plugins/locate/python/py-locate.c58
-rw-r--r--src/util/support/ChangeLog8
-rw-r--r--src/util/support/Makefile.in3
-rw-r--r--src/util/support/errors.c134
-rw-r--r--src/util/support/libkrb5support.exports6
-rw-r--r--src/util/support/threads.c4
23 files changed, 423 insertions, 32 deletions
diff --git a/src/clients/kinit/ChangeLog b/src/clients/kinit/ChangeLog
index 63d53ffa9..6b97d7a2b 100644
--- a/src/clients/kinit/ChangeLog
+++ b/src/clients/kinit/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-26 Ken Raeburn <raeburn@mit.edu>
+
+ * kinit.c (extended_com_err_fn): New function.
+ (errctx): New variable.
+ (k5_begin): Set errctx.
+ (k5_end): Clear it.
+ (main): Call set_com_err_hook.
+
2004-07-01 Ken Raeburn <raeburn@mit.edu>
* kinit.c (k5_kinit): Don't free addresses after calling
diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
index 6ffebadd4..8160822da 100644
--- a/src/clients/kinit/kinit.c
+++ b/src/clients/kinit/kinit.c
@@ -268,6 +268,18 @@ fprintf(stderr, USAGE_OPT_FMT, indent, col1)
exit(2);
}
+static krb5_context errctx;
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+ const char *fmt, va_list args)
+{
+ const char *emsg;
+ emsg = krb5_get_error_message (errctx, code);
+ fprintf (stderr, "%s: %s ", myprog, emsg);
+ krb5_free_error_message (errctx, emsg);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+}
+
static char *
parse_options(argc, argv, opts, progname)
int argc;
@@ -494,6 +506,7 @@ struct k4_data* k4;
com_err(progname, code, "while initializing Kerberos 5 library");
return 0;
}
+ errctx = k5->ctx;
if (opts->k5_cache_name)
{
code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc);
@@ -591,6 +604,7 @@ k5_end(k5)
krb5_cc_close(k5->ctx, k5->cc);
if (k5->ctx)
krb5_free_context(k5->ctx);
+ errctx = NULL;
memset(k5, 0, sizeof(*k5));
}
@@ -1098,6 +1112,8 @@ main(argc, argv)
memset(&k5, 0, sizeof(k5));
memset(&k4, 0, sizeof(k4));
+ set_com_err_hook (extended_com_err_fn);
+
parse_options(argc, argv, &opts, progname);
got_k5 = k5_begin(&opts, &k5, &k4);
diff --git a/src/clients/kvno/ChangeLog b/src/clients/kvno/ChangeLog
index 0a81427ff..0982dd036 100644
--- a/src/clients/kvno/ChangeLog
+++ b/src/clients/kvno/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-26 Ken Raeburn <raeburn@mit.edu>
+
+ * kvno.c: Include com_err.h.
+ (extended_com_err_fn): New function.
+ (context): New variable.
+ (main): Call set_com_err_hook.
+ (do_v5_kvno): Call com_err instead of fprintf+error_message.
+
2004-08-31 Tom Yu <tlyu@mit.edu>
* kvno.M: Update usage.
diff --git a/src/clients/kvno/kvno.c b/src/clients/kvno/kvno.c
index c860eb7d4..4accdb4a9 100644
--- a/src/clients/kvno/kvno.c
+++ b/src/clients/kvno/kvno.c
@@ -55,12 +55,18 @@ static void do_v4_kvno (int argc, char *argv[]);
static void do_v5_kvno (int argc, char *argv[],
char *ccachestr, char *etypestr);
+#include <com_err.h>
+static void extended_com_err_fn (const char *, errcode_t, const char *,
+ va_list);
+
int main(int argc, char *argv[])
{
int option;
char *etypestr = 0, *ccachestr = 0;
int v4 = 0;
+ set_com_err_hook (extended_com_err_fn);
+
prog = strrchr(argv[0], '/');
prog = prog ? (prog + 1) : argv[0];
@@ -149,10 +155,21 @@ static void do_v4_kvno (int count, char *names[])
}
#include <krb5.h>
+static krb5_context context;
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+ const char *fmt, va_list args)
+{
+ const char *emsg;
+ emsg = krb5_get_error_message (context, code);
+ fprintf (stderr, "%s: %s ", myprog, emsg);
+ krb5_free_error_message (context, emsg);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+}
+
static void do_v5_kvno (int count, char *names[],
char * ccachestr, char *etypestr)
{
- krb5_context context;
krb5_error_code ret;
int i, errors;
krb5_enctype etype;
@@ -203,16 +220,16 @@ static void do_v5_kvno (int count, char *names[],
ret = krb5_parse_name(context, names[i], &in_creds.server);
if (ret) {
if (!quiet)
- fprintf(stderr, "%s: %s while parsing principal name\n",
- names[i], error_message(ret));
+ com_err(prog, ret, "while parsing principal name %s", names[i]);
errors++;
continue;
}
ret = krb5_unparse_name(context, in_creds.server, &princ);
if (ret) {
- fprintf(stderr, "%s: %s while printing principal name\n",
- names[i], error_message(ret));
+ com_err(prog, ret,
+ "while formatting parsed principal name for '%s'",
+ names[i]);
errors++;
continue;
}
@@ -224,8 +241,7 @@ static void do_v5_kvno (int count, char *names[],
krb5_free_principal(context, in_creds.server);
if (ret) {
- fprintf(stderr, "%s: %s while getting credentials\n",
- princ, error_message(ret));
+ com_err(prog, ret, "while getting credentials for %s", princ);
krb5_free_unparsed_name(context, princ);
@@ -236,9 +252,7 @@ static void do_v5_kvno (int count, char *names[],
/* we need a native ticket */
ret = krb5_decode_ticket(&out_creds->ticket, &ticket);
if (ret) {
- fprintf(stderr, "%s: %s while decoding ticket\n",
- princ, error_message(ret));
-
+ com_err(prog, ret, "while decoding ticket for %s", princ);
krb5_free_creds(context, out_creds);
krb5_free_unparsed_name(context, princ);
diff --git a/src/include/ChangeLog b/src/include/ChangeLog
index cf62126c9..b5c4654a4 100644
--- a/src/include/ChangeLog
+++ b/src/include/ChangeLog
@@ -1,3 +1,12 @@
+2006-03-26 Ken Raeburn <raeburn@mit.edu>
+
+ * krb5.hin (krb5_set_error_message, krb5_vset_error_message,
+ krb5_get_error_message, krb5_free_error_message,
+ krb5_clear_error_message): Declare.
+ * k5-err.h: New file.
+ * k5-int.h: Include it.
+ (struct _krb5_context): Add new field ERR.
+
2006-03-11 Ken Raeburn <raeburn@mit.edu>
* adm.h, adm_defs.h, adm_proto.h, copyright.h, kdb.h, kdb_dbc.h,
diff --git a/src/include/k5-err.h b/src/include/k5-err.h
new file mode 100644
index 000000000..0ac20802b
--- /dev/null
+++ b/src/include/k5-err.h
@@ -0,0 +1,23 @@
+#define _(X) (X)
+#define KRB5_CALLCONV
+struct errinfo {
+ long code;
+ const char *msg;
+ char scratch_buf[1024];
+};
+
+void
+krb5int_set_error (struct errinfo *ep,
+ long code,
+ const char *fmt, ...);
+void
+krb5int_vset_error (struct errinfo *ep, long code,
+ const char *fmt, va_list args);
+char *
+krb5int_get_error (struct errinfo *ep, long code);
+void
+krb5int_free_error (struct errinfo *ep, char *msg);
+void
+krb5int_clear_error (struct errinfo *ep);
+void
+krb5int_set_error_info_callout_fn (const char *(KRB5_CALLCONV *f)(long));
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index ff8b34205..4b455f9fb 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -169,6 +169,9 @@ typedef INT64_TYPE krb5_int64;
/* Get mutex support; currently used only for the replay cache. */
#include "k5-thread.h"
+/* Get error info support. */
+#include "k5-err.h"
+
/* krb5/krb5.h includes many other .h files in the krb5 subdirectory.
The ones that it doesn't include, we include below. */
@@ -1067,6 +1070,9 @@ struct _krb5_context {
struct plugin_dir_handle libkrb5_plugins;
struct krb5plugin_service_locate_ftable *vtbl;
void (**locate_fptrs)(void);
+
+ /* error detail info */
+ struct errinfo err;
};
/* could be used in a table to find an etype and initialize a block */
diff --git a/src/include/krb5.hin b/src/include/krb5.hin
index eaaedec8f..d786e6770 100644
--- a/src/include/krb5.hin
+++ b/src/include/krb5.hin
@@ -2536,6 +2536,21 @@ typedef krb5_int32 krb5_prompt_type;
krb5_prompt_type* KRB5_CALLCONV krb5_get_prompt_types
(krb5_context context);
+/* Error reporting */
+void
+krb5_set_error_message (krb5_context, krb5_error_code, const char *, ...);
+#ifdef va_start
+void
+krb5_vset_error_message (krb5_context, krb5_error_code, const char *, va_list);
+#endif
+char *
+krb5_get_error_message (krb5_context, krb5_error_code);
+void
+krb5_free_error_message (krb5_context, char *);
+void
+krb5_clear_error_message (krb5_context);
+
+
#if TARGET_OS_MAC
# pragma options align=reset
#endif
diff --git a/src/lib/krb5/ChangeLog b/src/lib/krb5/ChangeLog
index f7849aea5..6cfd3e644 100644
--- a/src/lib/krb5/ChangeLog
+++ b/src/lib/krb5/ChangeLog
@@ -1,3 +1,10 @@
+2006-03-26 Ken Raeburn <raeburn@mit.edu>
+
+ * krb5_libinit.c (krb5int_lib_init): Register callback function
+ for lower-level error-info support routines.
+ (krb5int_lib_fini): Clear the callback function.
+ * libkrb5.exports: Export new error-message functions.
+
2005-11-14 Jeffrey Altman <jaltman@mit.edu>
* krb5_libinit.c: include k5-int.h instead of krb5.h
diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog
index ba3211c4c..4b5062d95 100644
--- a/src/lib/krb5/krb/ChangeLog
+++ b/src/lib/krb5/krb/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-26 Ken Raeburn <raeburn@mit.edu>
+
+ * kerrs.c: New file.
+ * Makefile.in (SRCS, OBJS, STLIBOBJS): Add it.
+
+ * gc_via_tkt.c (krb5_get_cred_via_tkt): If the KDC returns
+ KRB_ERR_GENERIC, store the e-text field as the error message.
+
2006-03-13 Ken Raeburn <raeburn@mit.edu>
* Makefile.in (check-unix): Use RUN_SETUP for t_deltat.
diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in
index 05249cabb..2a3d09de6 100644
--- a/src/lib/krb5/krb/Makefile.in
+++ b/src/lib/krb5/krb/Makefile.in
@@ -55,6 +55,7 @@ STLIBOBJS= \
init_ctx.o \
init_keyblock.o \
kdc_rep_dc.o \
+ kerrs.o \
kfree.o \
mk_cred.o \
mk_error.o \
@@ -140,7 +141,8 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \
$(OUTPRE)init_ctx.$(OBJEXT) \
$(OUTPRE)init_keyblock.$(OBJEXT) \
$(OUTPRE)kdc_rep_dc.$(OBJEXT) \
- $(OUTPRE)kfree.$(OBJEXT) \
+ $(OUTPRE)kerrs.$(OBJEXT) \
+ $(OUTPRE)kfree.$(OBJEXT) \
$(OUTPRE)mk_cred.$(OBJEXT) \
$(OUTPRE)mk_error.$(OBJEXT) \
$(OUTPRE)mk_priv.$(OBJEXT) \
@@ -226,6 +228,7 @@ SRCS= $(srcdir)/addr_comp.c \
$(srcdir)/init_ctx.c \
$(srcdir)/init_keyblock.c \
$(srcdir)/kdc_rep_dc.c \
+ $(srcdir)/kerrs.c \
$(srcdir)/kfree.c \
$(srcdir)/mk_cred.c \
$(srcdir)/mk_error.c \
diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c
index 1008d1f92..a1ed6e90d 100644
--- a/src/lib/krb5/krb/gc_via_tkt.c
+++ b/src/lib/krb5/krb/gc_via_tkt.c
@@ -171,6 +171,33 @@ krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt,
goto error_4;
retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
+ if (err_reply->text.length > 0) {
+ const char *m;
+ switch (err_reply->error) {
+ case KRB_ERR_GENERIC:
+ krb5_set_error_message(context, retval,
+ "KDC returned error string: %s",
+ err_reply->text.data);
+ break;
+ default:
+#if 0 /* We should stop the KDC from sending back this text, because
+ if the local language doesn't match the KDC's language, we'd
+ just wind up printing out the error message in two languages.
+ Well, when we get some localization. Which is already
+ happening in KfM. */
+ m = error_message(retval);
+ /* Special case: MIT KDC may return this same string
+ in the e-text field. */
+ if (strlen (m) == err_reply->text.length-1
+ && !strcmp(m, err_reply->text.data))
+ break;
+ krb5_set_error_message(context, retval,
+ "%s (KDC supplied additional data: %s)",
+ m, err_reply->text.data);
+#endif
+ break;
+ }
+ }
krb5_free_error(context, err_reply);
goto error_4;
diff --git a/src/lib/krb5/krb/kerrs.c b/src/lib/krb5/krb/kerrs.c
new file mode 100644
index 000000000..8439e2327
--- /dev/null
+++ b/src/lib/krb5/krb/kerrs.c
@@ -0,0 +1,48 @@
+/* foo */
+#include <stdarg.h>
+#include "k5-int.h"
+
+void
+krb5_set_error_message (krb5_context ctx, krb5_error_code code,
+ const char *fmt, ...)
+{
+ va_list args;
+ if (ctx == NULL)
+ return;
+ va_start (args, fmt);
+ krb5int_vset_error (&ctx->err, code, fmt, args);
+ va_end (args);
+}
+
+void
+krb5_vset_error_message (krb5_context ctx, krb5_error_code code,
+ const char *fmt, va_list args)
+{
+ if (ctx == NULL)
+ return;
+ krb5int_vset_error (&ctx->err, code, fmt, args);
+}
+
+char *
+krb5_get_error_message (krb5_context ctx, krb5_error_code code)
+{
+ if (ctx == NULL)
+ return error_message(code);
+ return krb5int_get_error (&ctx->err, code);
+}
+
+void
+krb5_free_error_message (krb5_context ctx, char *msg)
+{
+ if (ctx == NULL)
+ return;
+ krb5int_free_error (&ctx->err, msg);
+}
+
+void
+krb5_clear_error_message (krb5_context ctx)
+{
+ if (ctx == NULL)
+ return;
+ krb5int_clear_error (&ctx->err);
+}
diff --git a/src/lib/krb5/krb5_libinit.c b/src/lib/krb5/krb5_libinit.c
index 6771776ce..fce97ffb2 100644
--- a/src/lib/krb5/krb5_libinit.c
+++ b/src/lib/krb5/krb5_libinit.c
@@ -31,6 +31,8 @@ int krb5int_lib_init(void)
{
int err;
+ krb5int_set_error_info_callout_fn (error_message);
+
#ifdef SHOW_INITFINI_FUNCS
printf("krb5int_lib_init\n");
#endif
@@ -55,6 +57,7 @@ int krb5int_lib_init(void)
err = k5_mutex_finish_init(&krb5int_us_time_mutex);
if (err)
return err;
+
return 0;
}
@@ -98,6 +101,7 @@ void krb5int_lib_fini(void)
remove_error_table(&et_asn1_error_table);
remove_error_table(&et_k524_error_table);
#endif
+ krb5int_set_error_info_callout_fn (0);
}
/* Still exists because it went into the export list on Windows. But
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index f16b45cf8..8831bf781 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -726,3 +726,8 @@ profile_update_file_data
profile_update_relation
profile_verify_node
profile_write_tree_file
+krb5_set_error_message
+krb5_vset_error_message
+krb5_get_error_message
+krb5_free_error_message
+krb5_clear_error_message
diff --git a/src/plugins/locate/python/ChangeLog b/src/plugins/locate/python/ChangeLog
index 897919e11..db471def6 100644
--- a/src/plugins/locate/python/ChangeLog
+++ b/src/plugins/locate/python/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-26 Ken Raeburn <raeburn@mit.edu>
+
+ * Makefile.in (SHLIB_EXPLIBS, SHLIB_EXPDEPS): Add krb5 lib.
+ * py-locate.c (sctx): New variable.
+ (my_init, lookup): Call krb5_set_error_message instead of fprintf
+ in most cases. Use sctx to pass context (not thread safe!), and
+ store it as "blob" value.
+
2006-03-07 Ken Raeburn <raeburn@mit.edu>
* py-locate.c: Include k5-locate.h instead of k5-plugin.h.
diff --git a/src/plugins/locate/python/Makefile.in b/src/plugins/locate/python/Makefile.in
index 46a83fede..1d0b95964 100644
--- a/src/plugins/locate/python/Makefile.in
+++ b/src/plugins/locate/python/Makefile.in
@@ -10,8 +10,8 @@ SO_EXT=.so
RELDIR=../plugins/locate/python
MODULE_INSTALL_DIR = $(KRB5_LIBKRB5_MODULE_DIR)
-SHLIB_EXPDEPS=
-SHLIB_EXPLIBS= -lpython2.3
+SHLIB_EXPDEPS= $(KRB5_DEPLIB)
+SHLIB_EXPLIBS= -lpython2.3 $(KRB5_LIB)
SHLIB_DIRS=-L$(TOPLIBD)
SHLIB_RDIRS=$(KRB5_LIBDIR)
@@ -34,9 +34,10 @@ clean-unix:: clean-libs clean-libobjs
# the Makefile.in file
#
py-locate.so py-locate.po $(OUTPRE)py-locate.$(OBJEXT): \
- py-locate.c $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-int.h \
- $(BUILDTOP)/include/krb5/osconf.h $(SRCTOP)/include/k5-platform.h \
+ py-locate.c $(BUILDTOP)/include/autoconf.h $(SRCTOP)/include/k5-int.h \
+ $(BUILDTOP)/include/osconf.h $(SRCTOP)/include/k5-platform.h \
$(SRCTOP)/include/k5-thread.h $(BUILDTOP)/include/krb5.h \
$(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h $(SRCTOP)/include/port-sockets.h \
- $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
+ $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-locate.h $(SRCTOP)/include/kdb.h \
$(SRCTOP)/include/k5-plugin.h
diff --git a/src/plugins/locate/python/py-locate.c b/src/plugins/locate/python/py-locate.c
index 548210a6b..f5dc62932 100644
--- a/src/plugins/locate/python/py-locate.c
+++ b/src/plugins/locate/python/py-locate.c
@@ -79,6 +79,8 @@ MAKE_FINI_FUNCTION(my_fini);
#define F (strchr(__FILE__, '/') ? 1 + strrchr(__FILE__, '/') : __FILE__)
+static krb5_context sctx; /* XXX ugly hack! */
+
int
my_init (void)
{
@@ -88,8 +90,13 @@ my_init (void)
Py_Initialize ();
// fprintf(stderr, "trying to load %s\n", SCRIPT_PATH);
f = fopen(SCRIPT_PATH, "r");
- if (f == NULL)
+ if (f == NULL) {
+ if (sctx)
+ krb5_set_error_message(sctx, -1,
+ "couldn't open Python script %s (%s)",
+ SCRIPT_PATH, strerror(errno));
return -1;
+ }
PyRun_SimpleFile (f, SCRIPT_PATH);
fclose(f);
mainmodule = PyModule_GetDict(PyImport_AddModule("__main__"));
@@ -128,7 +135,7 @@ ctxinit (krb5_context ctx, void **blobptr)
interpreter, this would be a good place for it; the blob could
be allocated to hold the reference to the interpreter
instance. */
- *blobptr = 0;
+ *blobptr = ctx;
return 0;
}
@@ -164,10 +171,12 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
// fprintf(stderr, "%s:%d: lookup(%d,%s,%d,%d)\n", F, __LINE__,
// svc, realm, socktype, family);
+ sctx = blob; /* XXX: Not thread safe! */
i = CALL_INIT_FUNCTION (my_init);
if (i) {
- fprintf(stderr, "%s:%d: module initialization failed %d\n",
- F, __LINE__, i);
+#if 0
+ fprintf(stderr, "%s:%d: module initialization failed\n", F, __LINE__);
+#endif
return i;
}
if (locatefn == 0)
@@ -187,7 +196,13 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
py_result = PyObject_CallObject (locatefn, arglist);
Py_DECREF (arglist);
- if (PyErr_Occurred()) { fprintf(stderr,"%s:%d: python error\n", F, __LINE__); PyErr_Print(); return -1; }
+ if (PyErr_Occurred()) {
+ fprintf(stderr,"%s:%d: python error\n", F, __LINE__);
+ PyErr_Print();
+ krb5_set_error_message(blob, -1,
+ "Python evaluation error, see stderr");
+ return -1;
+ }
if (py_result == 0) {
fprintf(stderr, "%s:%d: returned null object\n", F, __LINE__);
return -1;
@@ -197,6 +212,8 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
if (! PyList_Check (py_result)) {
Py_DECREF (py_result);
fprintf(stderr, "%s:%d: returned non-list, non-False\n", F, __LINE__);
+ krb5_set_error_message(blob, -1,
+ "Python script error -- returned non-list, non-False result");
return -1;
}
listsize = PyList_Size (py_result);
@@ -211,20 +228,24 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
answer = PyList_GetItem (py_result, i);
if (! PyTuple_Check (answer)) {
- fprintf(stderr, "%s:%d: item %d non-tuple\n", F, __LINE__, i);
+ krb5_set_error_message(blob, -1,
+ "Python script error -- returned item %d not a tuple", i);
/* leak? */
return -1;
}
if (PyTuple_Size (answer) != 3) {
- fprintf(stderr, "%s:%d: item %d tuple size %d should be 3\n", F, __LINE__, i,
- PyTuple_Size (answer));
+ krb5_set_error_message(blob, -1,
+ "Python script error -- returned tuple %d size %d should be 3",
+ i, PyTuple_Size (answer));
/* leak? */
return -1;
}
field = PyTuple_GetItem (answer, 0);
if (! PyString_Check (field)) {
/* leak? */
- fprintf(stderr, "%s:%d: item %d first component not a string\n", F, __LINE__, i);
+ krb5_set_error_message(blob, -1,
+ "Python script error -- first component of tuple %d is not a string",
+ i);
return -1;
}
hoststr = PyString_AsString (field);
@@ -235,14 +256,17 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
sprintf(portbuf, "%ld", PyInt_AsLong (field));
portstr = portbuf;
} else {
- fprintf(stderr, "%s:%d: item %d second component neither string nor int\n",
- F, __LINE__, i);
+ krb5_set_error_message(blob, -1,
+ "Python script error -- second component of tuple %d neither a string nor an integer",
+ i);
/* leak? */
return -1;
}
field = PyTuple_GetItem (answer, 2);
if (! PyInt_Check (field)) {
- fprintf(stderr, "%s:%d: item %d third component not int\n", F, __LINE__, i);
+ krb5_set_error_message(blob, -1,
+ "Python script error -- third component of tuple %d not an integer",
+ i);
/* leak? */
return -1;
}
@@ -252,16 +276,18 @@ lookup (void *blob, enum locate_service_type svc, const char *realm,
case SOCK_DGRAM:
/* okay */
if (socktype != 0 && socktype != thissocktype) {
- fprintf(stderr, "%s:%d: item %d socket type %d should be %d\n",
- F, __LINE__, i, thissocktype, socktype);
+ krb5_set_error_message(blob, -1,
+ "Python script error -- tuple %d has socket type %d, should only have %d",
+ i, thissocktype, socktype);
/* leak? */
return -1;
}
break;
default:
/* 0 is not acceptable */
- fprintf(stderr, "%s:%d: item %d socket type %d invalid\n", F, __LINE__, i,
- thissocktype);
+ krb5_set_error_message(blob, -1,
+ "Python script error -- tuple %d has invalid socket type %d",
+ i, thissocktype);
/* leak? */
return -1;
}
diff --git a/src/util/support/ChangeLog b/src/util/support/ChangeLog
index 295f42f12..d1fae1dbe 100644
--- a/src/util/support/ChangeLog
+++ b/src/util/support/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-26 Ken Raeburn <raeburn@mit.edu>
+
+ * errors.c: New file.
+ * Makefile.in (SRCS, LIBOBJS, STLIBOBJS): Add it.
+ * threads.c (krb5int_thread_support_init): Call krb5int_err_init
+ to initialize the new file.
+ * libkrb5support.exports: Add the new symbols.
+
2006-03-13 Ken Raeburn <raeburn@mit.edu>
* plugins.c (krb5int_get_plugin_dir_data): If dirhandle is null or
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
index e6c75f525..2e96a88db 100644
--- a/src/util/support/Makefile.in
+++ b/src/util/support/Makefile.in
@@ -28,12 +28,14 @@ STLIBOBJS= \
threads.o \
init-addrinfo.o \
plugins.o \
+ errors.o \
fake-addrinfo.o
LIBOBJS= \
$(OUTPRE)threads.$(OBJEXT) \
$(OUTPRE)init-addrinfo.$(OBJEXT) \
$(OUTPRE)plugins.$(OBJEXT) \
+ $(OUTPRE)errors.$(OBJEXT) \
$(OUTPRE)fake-addrinfo.$(OBJEXT)
STOBJLISTS=OBJS.ST
@@ -45,6 +47,7 @@ LOCALINCLUDES=-I. -I$(srcdir)
SRCS=\
$(srcdir)/threads.c \
$(srcdir)/init-addrinfo.c \
+ $(srcdir)/errors.c \
$(srcdir)/fake-addrinfo.c
SHLIB_EXPDEPS =
# Add -lm if dumping thread stats, for sqrt.
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();
+}
diff --git a/src/util/support/libkrb5support.exports b/src/util/support/libkrb5support.exports
index 1d7bc717f..00ce5c3e3 100644
--- a/src/util/support/libkrb5support.exports
+++ b/src/util/support/libkrb5support.exports
@@ -25,3 +25,9 @@ krb5int_mutex_alloc
krb5int_mutex_free
krb5int_mutex_lock
krb5int_mutex_unlock
+krb5int_set_error
+krb5int_vset_error
+krb5int_get_error
+krb5int_free_error
+krb5int_clear_error
+krb5int_set_error_info_callout_fn
diff --git a/src/util/support/threads.c b/src/util/support/threads.c
index d0697bd93..7dc2e4828 100644
--- a/src/util/support/threads.c
+++ b/src/util/support/threads.c
@@ -453,6 +453,10 @@ int krb5int_thread_support_init (void)
if (err)
return err;
+ err = krb5int_err_init();
+ if (err)
+ return err;
+
return 0;
}