|
Packit |
fd8b60 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* Copyright 1997,2000,2001,2004,2008 by Massachusetts Institute of Technology
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Copyright 1987, 1988 by MIT Student Information Processing Board
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* Permission to use, copy, modify, and distribute this software
|
|
Packit |
fd8b60 |
* and its documentation for any purpose and without fee is
|
|
Packit |
fd8b60 |
* hereby granted, provided that the above copyright notice
|
|
Packit |
fd8b60 |
* appear in all copies and that both that copyright notice and
|
|
Packit |
fd8b60 |
* this permission notice appear in supporting documentation,
|
|
Packit |
fd8b60 |
* and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
|
Packit |
fd8b60 |
* used in advertising or publicity pertaining to distribution
|
|
Packit |
fd8b60 |
* of the software without specific, written prior permission.
|
|
Packit |
fd8b60 |
* Furthermore if you modify this software you must label
|
|
Packit |
fd8b60 |
* your software as modified software and not distribute it in such a
|
|
Packit |
fd8b60 |
* fashion that it might be confused with the original M.I.T. software.
|
|
Packit |
fd8b60 |
* M.I.T. and the M.I.T. S.I.P.B. make no representations about
|
|
Packit |
fd8b60 |
* the suitability of this software for any purpose. It is
|
|
Packit |
fd8b60 |
* provided "as is" without express or implied warranty.
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include "k5-platform.h"
|
|
Packit |
fd8b60 |
#include "com_err.h"
|
|
Packit |
fd8b60 |
#include "error_table.h"
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static struct et_list *et_list;
|
|
Packit |
fd8b60 |
static k5_mutex_t et_list_lock = K5_MUTEX_PARTIAL_INITIALIZER;
|
|
rpm-build |
28718a |
static int terminated = 0; /* for safety and finalization debugging */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
MAKE_INIT_FUNCTION(com_err_initialize);
|
|
Packit |
fd8b60 |
MAKE_FINI_FUNCTION(com_err_terminate);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
int com_err_initialize(void)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
int err;
|
|
Packit |
fd8b60 |
#ifdef SHOW_INITFINI_FUNCS
|
|
Packit |
fd8b60 |
printf("com_err_initialize\n");
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
terminated = 0;
|
|
Packit |
fd8b60 |
err = k5_mutex_finish_init(&et_list_lock);
|
|
Packit |
fd8b60 |
if (err)
|
|
Packit |
fd8b60 |
return err;
|
|
Packit |
fd8b60 |
err = k5_mutex_finish_init(&com_err_hook_lock);
|
|
Packit |
fd8b60 |
if (err)
|
|
Packit |
fd8b60 |
return err;
|
|
Packit |
fd8b60 |
err = k5_key_register(K5_KEY_COM_ERR, free);
|
|
Packit |
fd8b60 |
if (err)
|
|
Packit |
fd8b60 |
return err;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
void com_err_terminate(void)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
struct et_list *e, *enext;
|
|
Packit |
fd8b60 |
if (! INITIALIZER_RAN(com_err_initialize) || PROGRAM_EXITING()) {
|
|
Packit |
fd8b60 |
#ifdef SHOW_INITFINI_FUNCS
|
|
Packit |
fd8b60 |
printf("com_err_terminate: skipping\n");
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
return;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#ifdef SHOW_INITFINI_FUNCS
|
|
Packit |
fd8b60 |
printf("com_err_terminate\n");
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
k5_key_delete(K5_KEY_COM_ERR);
|
|
Packit |
fd8b60 |
k5_mutex_destroy(&com_err_hook_lock);
|
|
Packit |
fd8b60 |
k5_mutex_lock(&et_list_lock);
|
|
Packit |
fd8b60 |
for (e = et_list; e; e = enext) {
|
|
Packit |
fd8b60 |
enext = e->next;
|
|
Packit |
fd8b60 |
free(e);
|
|
Packit |
fd8b60 |
}
|
|
rpm-build |
28718a |
et_list = NULL;
|
|
Packit |
fd8b60 |
k5_mutex_unlock(&et_list_lock);
|
|
Packit |
fd8b60 |
k5_mutex_destroy(&et_list_lock);
|
|
Packit |
fd8b60 |
terminated = 1;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#ifndef DEBUG_TABLE_LIST
|
|
Packit |
fd8b60 |
#define dprintf(X)
|
|
Packit |
fd8b60 |
#else
|
|
Packit |
fd8b60 |
#define dprintf(X) printf X
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static char *
|
|
Packit |
fd8b60 |
get_thread_buffer ()
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
char *cp;
|
|
Packit |
fd8b60 |
cp = k5_getspecific(K5_KEY_COM_ERR);
|
|
Packit |
fd8b60 |
if (cp == NULL) {
|
|
Packit |
fd8b60 |
cp = malloc(ET_EBUFSIZ);
|
|
Packit |
fd8b60 |
if (cp == NULL) {
|
|
Packit |
fd8b60 |
return NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
if (k5_setspecific(K5_KEY_COM_ERR, cp) != 0) {
|
|
Packit |
fd8b60 |
free(cp);
|
|
Packit |
fd8b60 |
return NULL;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
return cp;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
const char * KRB5_CALLCONV
|
|
Packit |
fd8b60 |
error_message(long code)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
unsigned long offset;
|
|
Packit |
fd8b60 |
unsigned long l_offset;
|
|
Packit |
fd8b60 |
struct et_list *e;
|
|
Packit |
fd8b60 |
unsigned long table_num;
|
|
Packit |
fd8b60 |
int started = 0;
|
|
Packit |
fd8b60 |
unsigned int divisor = 100;
|
|
Packit |
fd8b60 |
char *cp, *cp1;
|
|
Packit |
fd8b60 |
const struct error_table *table;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (CALL_INIT_FUNCTION(com_err_initialize))
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
l_offset = (unsigned long)code & ((1<
|
|
Packit |
fd8b60 |
offset = l_offset;
|
|
Packit |
fd8b60 |
table_num = ((unsigned long)code - l_offset) & ERRCODE_MAX;
|
|
Packit |
fd8b60 |
if (table_num == 0
|
|
Packit |
fd8b60 |
#ifdef __sgi
|
|
Packit |
fd8b60 |
/* Irix 6.5 uses a much bigger table than other UNIX
|
|
Packit |
fd8b60 |
systems I've looked at, but the table is sparse. The
|
|
Packit |
fd8b60 |
sparse entries start around 500, but sys_nerr is only
|
|
Packit |
fd8b60 |
152. */
|
|
Packit |
fd8b60 |
|| (code > 0 && code <= 1600)
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
) {
|
|
Packit |
fd8b60 |
if (code == 0)
|
|
Packit |
fd8b60 |
goto oops;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* This could trip if int is 16 bits. */
|
|
Packit |
fd8b60 |
if ((unsigned long)(int)code != (unsigned long)code)
|
|
Packit |
fd8b60 |
abort ();
|
|
Packit |
fd8b60 |
cp = get_thread_buffer();
|
|
Packit |
fd8b60 |
if (cp && strerror_r(code, cp, ET_EBUFSIZ) == 0)
|
|
Packit |
fd8b60 |
return cp;
|
|
Packit |
fd8b60 |
return strerror(code);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
k5_mutex_lock(&et_list_lock);
|
|
Packit |
fd8b60 |
dprintf(("scanning list for %x\n", table_num));
|
|
Packit |
fd8b60 |
for (e = et_list; e != NULL; e = e->next) {
|
|
Packit |
fd8b60 |
dprintf(("\t%x = %s\n", e->table->base & ERRCODE_MAX,
|
|
Packit |
fd8b60 |
e->table->msgs[0]));
|
|
Packit |
fd8b60 |
if ((e->table->base & ERRCODE_MAX) == table_num) {
|
|
Packit |
fd8b60 |
table = e->table;
|
|
Packit |
fd8b60 |
goto found;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
goto no_table_found;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
found:
|
|
Packit |
fd8b60 |
k5_mutex_unlock(&et_list_lock);
|
|
Packit |
fd8b60 |
dprintf (("found it!\n"));
|
|
Packit |
fd8b60 |
/* This is the right table */
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* This could trip if int is 16 bits. */
|
|
Packit |
fd8b60 |
if ((unsigned long)(unsigned int)offset != offset)
|
|
Packit |
fd8b60 |
goto no_table_found;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (table->n_msgs <= (unsigned int) offset)
|
|
Packit |
fd8b60 |
goto no_table_found;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* If there's a string at the end of the table, it's a text domain. */
|
|
Packit |
fd8b60 |
if (table->msgs[table->n_msgs] != NULL)
|
|
Packit |
fd8b60 |
return dgettext(table->msgs[table->n_msgs], table->msgs[offset]);
|
|
Packit |
fd8b60 |
else
|
|
Packit |
fd8b60 |
return table->msgs[offset];
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
no_table_found:
|
|
Packit |
fd8b60 |
k5_mutex_unlock(&et_list_lock);
|
|
Packit |
fd8b60 |
#if defined(_WIN32)
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* WinSock errors exist in the 10000 and 11000 ranges
|
|
Packit |
fd8b60 |
* but might not appear if WinSock is not initialized
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
if (code >= WSABASEERR && code < WSABASEERR + 1100) {
|
|
Packit |
fd8b60 |
table_num = 0;
|
|
Packit |
fd8b60 |
offset = code;
|
|
Packit |
fd8b60 |
divisor = WSABASEERR;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
#ifdef _WIN32
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
LPVOID msgbuf;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (! FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
Packit |
fd8b60 |
NULL /* lpSource */,
|
|
Packit |
fd8b60 |
(DWORD) code,
|
|
Packit |
fd8b60 |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
Packit |
fd8b60 |
(LPTSTR) &msgbuf,
|
|
Packit |
fd8b60 |
(DWORD) 0 /*sizeof(buffer)*/,
|
|
Packit |
fd8b60 |
NULL /* va_list */ )) {
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* WinSock errors exist in the 10000 and 11000 ranges
|
|
Packit |
fd8b60 |
* but might not appear if WinSock is not initialized
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
if (code >= WSABASEERR && code < WSABASEERR + 1100) {
|
|
Packit |
fd8b60 |
table_num = 0;
|
|
Packit |
fd8b60 |
offset = code;
|
|
Packit |
fd8b60 |
divisor = 10000;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
goto oops;
|
|
Packit |
fd8b60 |
} else {
|
|
Packit |
fd8b60 |
char *buffer;
|
|
Packit |
fd8b60 |
cp = get_thread_buffer();
|
|
Packit |
fd8b60 |
if (cp == NULL)
|
|
Packit |
fd8b60 |
return "Unknown error code";
|
|
Packit |
fd8b60 |
buffer = cp;
|
|
Packit |
fd8b60 |
strncpy(buffer, msgbuf, ET_EBUFSIZ);
|
|
Packit |
fd8b60 |
buffer[ET_EBUFSIZ-1] = '\0';
|
|
Packit |
fd8b60 |
cp = buffer + strlen(buffer) - 1;
|
|
Packit |
fd8b60 |
if (*cp == '\n') *cp-- = '\0';
|
|
Packit |
fd8b60 |
if (*cp == '\r') *cp-- = '\0';
|
|
Packit |
fd8b60 |
if (*cp == '.') *cp-- = '\0';
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
LocalFree(msgbuf);
|
|
Packit |
fd8b60 |
return buffer;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
#endif
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
oops:
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
cp = get_thread_buffer();
|
|
Packit |
fd8b60 |
if (cp == NULL)
|
|
Packit |
fd8b60 |
return "Unknown error code";
|
|
Packit |
fd8b60 |
cp1 = cp;
|
|
Packit |
fd8b60 |
strlcpy(cp, "Unknown code ", ET_EBUFSIZ);
|
|
Packit |
fd8b60 |
cp += sizeof("Unknown code ") - 1;
|
|
Packit |
fd8b60 |
if (table_num != 0L) {
|
|
Packit |
fd8b60 |
(void) error_table_name_r(table_num, cp);
|
|
Packit |
fd8b60 |
while (*cp != '\0')
|
|
Packit |
fd8b60 |
cp++;
|
|
Packit |
fd8b60 |
*cp++ = ' ';
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
while (divisor > 1) {
|
|
Packit |
fd8b60 |
if (started != 0 || offset >= divisor) {
|
|
Packit |
fd8b60 |
*cp++ = '0' + offset / divisor;
|
|
Packit |
fd8b60 |
offset %= divisor;
|
|
Packit |
fd8b60 |
started++;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
divisor /= 10;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
*cp++ = '0' + offset;
|
|
Packit |
fd8b60 |
*cp = '\0';
|
|
Packit |
fd8b60 |
return(cp1);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
errcode_t KRB5_CALLCONV
|
|
Packit |
fd8b60 |
add_error_table(const struct error_table *et)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
struct et_list *e;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (CALL_INIT_FUNCTION(com_err_initialize))
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
e = malloc(sizeof(struct et_list));
|
|
Packit |
fd8b60 |
if (e == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
e->table = et;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
k5_mutex_lock(&et_list_lock);
|
|
Packit |
fd8b60 |
e->next = et_list;
|
|
Packit |
fd8b60 |
et_list = e;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* If there are two strings at the end of the table, they are a text domain
|
|
Packit |
fd8b60 |
* and locale dir, and we are supposed to call bindtextdomain. */
|
|
Packit |
fd8b60 |
if (et->msgs[et->n_msgs] != NULL && et->msgs[et->n_msgs + 1] != NULL)
|
|
Packit |
fd8b60 |
bindtextdomain(et->msgs[et->n_msgs], et->msgs[et->n_msgs + 1]);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
k5_mutex_unlock(&et_list_lock);
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
errcode_t KRB5_CALLCONV
|
|
Packit |
fd8b60 |
remove_error_table(const struct error_table *et)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
struct et_list **ep, *e;
|
|
Packit |
fd8b60 |
|
|
rpm-build |
28718a |
/* Safety check in case libraries are finalized in the wrong order. */
|
|
rpm-build |
28718a |
if (terminated)
|
|
rpm-build |
28718a |
return ENOENT;
|
|
rpm-build |
28718a |
|
|
Packit |
fd8b60 |
if (CALL_INIT_FUNCTION(com_err_initialize))
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
k5_mutex_lock(&et_list_lock);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/* Remove the entry that matches the error table instance. */
|
|
Packit |
fd8b60 |
for (ep = &et_list; *ep; ep = &(*ep)->next) {
|
|
Packit |
fd8b60 |
if ((*ep)->table == et) {
|
|
Packit |
fd8b60 |
e = *ep;
|
|
Packit |
fd8b60 |
*ep = e->next;
|
|
Packit |
fd8b60 |
free(e);
|
|
Packit |
fd8b60 |
k5_mutex_unlock(&et_list_lock);
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
k5_mutex_unlock(&et_list_lock);
|
|
Packit |
fd8b60 |
return ENOENT;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
int com_err_finish_init()
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return CALL_INIT_FUNCTION(com_err_initialize);
|
|
Packit |
fd8b60 |
}
|