Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/util/et/error_message.c
34907 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright 1997,2000,2001,2004,2008 by Massachusetts Institute of Technology
4
*
5
* Copyright 1987, 1988 by MIT Student Information Processing Board
6
*
7
* Permission to use, copy, modify, and distribute this software
8
* and its documentation for any purpose and without fee is
9
* hereby granted, provided that the above copyright notice
10
* appear in all copies and that both that copyright notice and
11
* this permission notice appear in supporting documentation,
12
* and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
13
* used in advertising or publicity pertaining to distribution
14
* of the software without specific, written prior permission.
15
* Furthermore if you modify this software you must label
16
* your software as modified software and not distribute it in such a
17
* fashion that it might be confused with the original M.I.T. software.
18
* M.I.T. and the M.I.T. S.I.P.B. make no representations about
19
* the suitability of this software for any purpose. It is
20
* provided "as is" without express or implied warranty.
21
*/
22
23
#include "k5-platform.h"
24
#include "com_err.h"
25
#include "error_table.h"
26
27
static struct et_list *et_list;
28
static k5_mutex_t et_list_lock = K5_MUTEX_PARTIAL_INITIALIZER;
29
static int terminated = 0; /* for safety and finalization debugging */
30
31
MAKE_INIT_FUNCTION(com_err_initialize);
32
MAKE_FINI_FUNCTION(com_err_terminate);
33
34
int com_err_initialize(void)
35
{
36
int err;
37
#ifdef SHOW_INITFINI_FUNCS
38
printf("com_err_initialize\n");
39
#endif
40
terminated = 0;
41
err = k5_mutex_finish_init(&et_list_lock);
42
if (err)
43
return err;
44
err = k5_mutex_finish_init(&com_err_hook_lock);
45
if (err)
46
return err;
47
err = k5_key_register(K5_KEY_COM_ERR, free);
48
if (err)
49
return err;
50
return 0;
51
}
52
53
void com_err_terminate(void)
54
{
55
struct et_list *e, *enext;
56
if (! INITIALIZER_RAN(com_err_initialize) || PROGRAM_EXITING()) {
57
#ifdef SHOW_INITFINI_FUNCS
58
printf("com_err_terminate: skipping\n");
59
#endif
60
return;
61
}
62
#ifdef SHOW_INITFINI_FUNCS
63
printf("com_err_terminate\n");
64
#endif
65
k5_key_delete(K5_KEY_COM_ERR);
66
k5_mutex_destroy(&com_err_hook_lock);
67
k5_mutex_lock(&et_list_lock);
68
for (e = et_list; e; e = enext) {
69
enext = e->next;
70
free(e);
71
}
72
et_list = NULL;
73
k5_mutex_unlock(&et_list_lock);
74
k5_mutex_destroy(&et_list_lock);
75
terminated = 1;
76
}
77
78
#ifndef DEBUG_TABLE_LIST
79
#define dprintf(X)
80
#else
81
#define dprintf(X) printf X
82
#endif
83
84
static char *
85
get_thread_buffer(void)
86
{
87
char *cp;
88
cp = k5_getspecific(K5_KEY_COM_ERR);
89
if (cp == NULL) {
90
cp = malloc(ET_EBUFSIZ);
91
if (cp == NULL) {
92
return NULL;
93
}
94
if (k5_setspecific(K5_KEY_COM_ERR, cp) != 0) {
95
free(cp);
96
return NULL;
97
}
98
}
99
return cp;
100
}
101
102
const char * KRB5_CALLCONV
103
error_message(long code)
104
{
105
unsigned long offset;
106
unsigned long l_offset;
107
struct et_list *e;
108
unsigned long table_num;
109
int started = 0;
110
unsigned int divisor = 100;
111
char *cp, *cp1;
112
const struct error_table *table;
113
114
if (CALL_INIT_FUNCTION(com_err_initialize))
115
return 0;
116
117
l_offset = (unsigned long)code & ((1<<ERRCODE_RANGE)-1);
118
offset = l_offset;
119
table_num = ((unsigned long)code - l_offset) & ERRCODE_MAX;
120
if (table_num == 0
121
#ifdef __sgi
122
/* Irix 6.5 uses a much bigger table than other UNIX
123
systems I've looked at, but the table is sparse. The
124
sparse entries start around 500, but sys_nerr is only
125
152. */
126
|| (code > 0 && code <= 1600)
127
#endif
128
) {
129
if (code == 0)
130
goto oops;
131
132
/* This could trip if int is 16 bits. */
133
if ((unsigned long)(int)code != (unsigned long)code)
134
abort ();
135
cp = get_thread_buffer();
136
if (cp && strerror_r(code, cp, ET_EBUFSIZ) == 0)
137
return cp;
138
return strerror(code);
139
}
140
141
k5_mutex_lock(&et_list_lock);
142
dprintf(("scanning list for %x\n", table_num));
143
for (e = et_list; e != NULL; e = e->next) {
144
dprintf(("\t%x = %s\n", e->table->base & ERRCODE_MAX,
145
e->table->msgs[0]));
146
if ((e->table->base & ERRCODE_MAX) == table_num) {
147
table = e->table;
148
goto found;
149
}
150
}
151
goto no_table_found;
152
153
found:
154
k5_mutex_unlock(&et_list_lock);
155
dprintf (("found it!\n"));
156
/* This is the right table */
157
158
/* This could trip if int is 16 bits. */
159
if ((unsigned long)(unsigned int)offset != offset)
160
goto no_table_found;
161
162
if (table->n_msgs <= (unsigned int) offset)
163
goto no_table_found;
164
165
/* If there's a string at the end of the table, it's a text domain. */
166
if (table->msgs[table->n_msgs] != NULL)
167
return dgettext(table->msgs[table->n_msgs], table->msgs[offset]);
168
else
169
return table->msgs[offset];
170
171
no_table_found:
172
k5_mutex_unlock(&et_list_lock);
173
#if defined(_WIN32)
174
/*
175
* WinSock errors exist in the 10000 and 11000 ranges
176
* but might not appear if WinSock is not initialized
177
*/
178
if (code >= WSABASEERR && code < WSABASEERR + 1100) {
179
table_num = 0;
180
offset = code;
181
divisor = WSABASEERR;
182
}
183
#endif
184
#ifdef _WIN32
185
{
186
LPVOID msgbuf;
187
188
if (! FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
189
NULL /* lpSource */,
190
(DWORD) code,
191
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
192
(LPTSTR) &msgbuf,
193
(DWORD) 0 /*sizeof(buffer)*/,
194
NULL /* va_list */ )) {
195
/*
196
* WinSock errors exist in the 10000 and 11000 ranges
197
* but might not appear if WinSock is not initialized
198
*/
199
if (code >= WSABASEERR && code < WSABASEERR + 1100) {
200
table_num = 0;
201
offset = code;
202
divisor = 10000;
203
}
204
205
goto oops;
206
} else {
207
char *buffer;
208
cp = get_thread_buffer();
209
if (cp == NULL)
210
return "Unknown error code";
211
buffer = cp;
212
strncpy(buffer, msgbuf, ET_EBUFSIZ);
213
buffer[ET_EBUFSIZ-1] = '\0';
214
cp = buffer + strlen(buffer) - 1;
215
if (*cp == '\n') *cp-- = '\0';
216
if (*cp == '\r') *cp-- = '\0';
217
if (*cp == '.') *cp-- = '\0';
218
219
LocalFree(msgbuf);
220
return buffer;
221
}
222
}
223
#endif
224
225
oops:
226
227
cp = get_thread_buffer();
228
if (cp == NULL)
229
return "Unknown error code";
230
cp1 = cp;
231
strlcpy(cp, "Unknown code ", ET_EBUFSIZ);
232
cp += sizeof("Unknown code ") - 1;
233
if (table_num != 0L) {
234
(void) error_table_name_r(table_num, cp);
235
while (*cp != '\0')
236
cp++;
237
*cp++ = ' ';
238
}
239
while (divisor > 1) {
240
if (started != 0 || offset >= divisor) {
241
*cp++ = '0' + offset / divisor;
242
offset %= divisor;
243
started++;
244
}
245
divisor /= 10;
246
}
247
*cp++ = '0' + offset;
248
*cp = '\0';
249
return(cp1);
250
}
251
252
errcode_t KRB5_CALLCONV
253
add_error_table(const struct error_table *et)
254
{
255
struct et_list *e;
256
257
if (CALL_INIT_FUNCTION(com_err_initialize))
258
return 0;
259
260
e = malloc(sizeof(struct et_list));
261
if (e == NULL)
262
return ENOMEM;
263
264
e->table = et;
265
266
k5_mutex_lock(&et_list_lock);
267
e->next = et_list;
268
et_list = e;
269
270
/* If there are two strings at the end of the table, they are a text domain
271
* and locale dir, and we are supposed to call bindtextdomain. */
272
if (et->msgs[et->n_msgs] != NULL && et->msgs[et->n_msgs + 1] != NULL)
273
bindtextdomain(et->msgs[et->n_msgs], et->msgs[et->n_msgs + 1]);
274
275
k5_mutex_unlock(&et_list_lock);
276
return 0;
277
}
278
279
errcode_t KRB5_CALLCONV
280
remove_error_table(const struct error_table *et)
281
{
282
struct et_list **ep, *e;
283
284
/* Safety check in case libraries are finalized in the wrong order. */
285
if (terminated)
286
return ENOENT;
287
288
if (CALL_INIT_FUNCTION(com_err_initialize))
289
return 0;
290
k5_mutex_lock(&et_list_lock);
291
292
/* Remove the entry that matches the error table instance. */
293
for (ep = &et_list; *ep; ep = &(*ep)->next) {
294
if ((*ep)->table == et) {
295
e = *ep;
296
*ep = e->next;
297
free(e);
298
k5_mutex_unlock(&et_list_lock);
299
return 0;
300
}
301
}
302
k5_mutex_unlock(&et_list_lock);
303
return ENOENT;
304
}
305
306
int com_err_finish_init(void)
307
{
308
return CALL_INIT_FUNCTION(com_err_initialize);
309
}
310
311