1/*
2 * Copyright (c) 1997 - 2002 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
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include "com_err.h"
39
40struct et_list *_et_list = NULL;
41
42
43KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
44error_message (long code)
45{
46    static char msg[128];
47    const char *p = com_right(_et_list, code);
48    if (p == NULL) {
49	if (code < 0)
50	    snprintf(msg, sizeof(msg), "Unknown error %ld", code);
51	else
52	    p = strerror(code);
53    }
54    if (p != NULL && *p != '\0') {
55	strlcpy(msg, p, sizeof(msg));
56    } else
57	snprintf(msg, sizeof(msg), "Unknown error %ld", code);
58    return msg;
59}
60
61KRB5_LIB_FUNCTION int KRB5_LIB_CALL
62init_error_table(const char **msgs, long base, int count)
63{
64    initialize_error_table_r(&_et_list, msgs, count, base);
65    return 0;
66}
67
68static void KRB5_CALLCONV
69default_proc (const char *whoami, long code, const char *fmt, va_list args)
70    __attribute__((__format__(__printf__, 3, 0)));
71
72static void KRB5_CALLCONV
73default_proc (const char *whoami, long code, const char *fmt, va_list args)
74{
75    if (whoami)
76      fprintf(stderr, "%s: ", whoami);
77    if (code)
78      fprintf(stderr, "%s ", error_message(code));
79    if (fmt)
80      vfprintf(stderr, fmt, args);
81    fprintf(stderr, "\r\n");	/* ??? */
82}
83
84static errf com_err_hook = default_proc;
85
86KRB5_LIB_FUNCTION void KRB5_LIB_CALL
87com_err_va (const char *whoami,
88	    long code,
89	    const char *fmt,
90	    va_list args)
91{
92    (*com_err_hook) (whoami, code, fmt, args);
93}
94
95KRB5_LIB_FUNCTION void KRB5_LIB_CALL
96com_err (const char *whoami,
97	 long code,
98	 const char *fmt,
99	 ...)
100{
101    va_list ap;
102    va_start(ap, fmt);
103    com_err_va (whoami, code, fmt, ap);
104    va_end(ap);
105}
106
107KRB5_LIB_FUNCTION errf KRB5_LIB_CALL
108set_com_err_hook (errf new)
109{
110    errf old = com_err_hook;
111
112    if (new)
113	com_err_hook = new;
114    else
115	com_err_hook = default_proc;
116
117    return old;
118}
119
120KRB5_LIB_FUNCTION errf KRB5_LIB_CALL
121reset_com_err_hook (void)
122{
123    return set_com_err_hook(NULL);
124}
125
126#define ERRCODE_RANGE   8       /* # of bits to shift table number */
127#define BITS_PER_CHAR   6       /* # bits to shift per character in name */
128
129static const char char_set[] =
130        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
131
132static char buf[6];
133
134KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
135error_table_name(int num)
136{
137    int ch;
138    int i;
139    char *p;
140
141    /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
142    p = buf;
143    num >>= ERRCODE_RANGE;
144    /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
145    num &= 077777777;
146    /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
147    for (i = 4; i >= 0; i--) {
148        ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
149        if (ch != 0)
150            *p++ = char_set[ch-1];
151    }
152    *p = '\0';
153    return(buf);
154}
155
156KRB5_LIB_FUNCTION void KRB5_LIB_CALL
157add_to_error_table(struct et_list *new_table)
158{
159    struct et_list *et;
160
161    for (et = _et_list; et; et = et->next) {
162	if (et->table->base == new_table->table->base)
163	    return;
164    }
165
166    new_table->next = _et_list;
167    _et_list = new_table;
168}
169