2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * Copyright 1997 by Massachusetts Institute of Technology
10 * Copyright 1987, 1988 by MIT Student Information Processing Board
12 * Permission to use, copy, modify, and distribute this software
13 * and its documentation for any purpose and without fee is
14 * hereby granted, provided that the above copyright notice
15 * appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation,
17 * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
18 * used in advertising or publicity pertaining to distribution
19 * of the software without specific, written prior permission.
20 * Furthermore if you modify this software you must label
21 * your software as modified software and not distribute it in such a
22 * fashion that it might be confused with the original M.I.T. software.
23 * M.I.T. and the M.I.T. S.I.P.B. make no representations about
24 * the suitability of this software for any purpose. It is
25 * provided "as is" without express or implied warranty.
34 #include "error_table.h"
40 k5_mutex_t com_err_hook_lock
= K5_MUTEX_PARTIAL_INITIALIZER
;
42 static void default_com_err_proc
43 (const char *whoami
, errcode_t code
,
44 const char *fmt
, va_list ap
);
50 mypid
= GetCurrentProcessId();
51 myprocess
= OpenProcess( PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, mypid
);
52 return GetGuiResources(myprocess
, 1) > 0;
58 * It is sometimes desirable to have more than a single hook called
59 * when com_err() is invoked. A number of new functions have been
60 * added which allow hooks to be added and removed:
62 * add_default_com_err_hook()
63 * remove_com_err_hook()
64 * remove_default_com_err_hook()
65 * The existing functions:
67 * reset_com_err_hook()
69 * have been modified to work with the new scheme. Applications using
70 * the original function calls are not affected.
73 static et_old_error_hook_func com_err_hook
[MAX_HOOKS
] = { default_com_err_proc
,
75 static int hook_count
= 1;
77 /* Solaris Kerberos specific fix start --------------------------- */
86 struct msg_map msgmap
[] = {
89 { gettext("%s\n## com_err msg of format: 'while ...'"),
92 #define MSG_ERROR_MSG 1
93 { gettext("%s\n## com_err message of format: 'error msg ...'"),
96 #define MSG_ERROR_MSG_WHILE 2
97 { gettext("%1$s %2$s\n## com_err message of format: "
98 "'error msg ... while ...'"),
101 #define MSG_WHOAMI_WHILE 3
102 { gettext("%1$s: %2$s\n## com_err msg of format: 'whoami: while ...'"),
105 #define MSG_WHOAMI_ERROR_MSG 4
106 { gettext("%1$s: %2$s\n## com_err message of format: "
107 "'whoami: error msg ...'"),
110 #define MSG_WHOAMI_ERROR_MSG_WHILE 5
111 { gettext("%1$s: %2$s %3$s\n## com_err message of format: "
112 "'whoami: error msg ... while ...'"),
113 "%1$s: %2$s %3$s\n" },
116 { gettext("%s:\n ## com_err message of format: "
117 "'whoami: with no error msg or while ...'"),
124 * The idea is that we provide a unique message id that contains extra junk
125 * that we never want to display in the C locale. If dgettext() returns
126 * a string that is equal to the message id, then we return the c_msgstr,
127 * for display in the locale.
130 my_gettext(int msg_idx
)
132 char *msgid
= msgmap
[msg_idx
].msgid
;
133 char *c_msgstr
= msgmap
[msg_idx
].c_msgstr
;
134 char *msgstr
= dgettext(TEXT_DOMAIN
, msgid
);
136 if (strcmp(msgstr
, msgid
) == 0)
142 /* Solaris Kerberos specific fix end --------------------------- */
144 /* Solaris Kerberos: this code is significantly altered from
145 * the MIT 1.2.1 version to work with internationalization */
147 static void default_com_err_proc (const char *whoami
, errcode_t code
,
148 const char *fmt
, va_list ap
)
150 char whilebuf
[1024] = "";
155 * Because 'while ...' message could contain a format string
156 * we have to intepret it now, in a buffer. We need to put it
157 * into a buffer so that the message can be juxtaposed in a locale
158 * meaningful manner. In some natural languages, the 'while ...' phrase
162 vsprintf(whilebuf
, fmt
, ap
);
166 * There are 8 possible combinations here depending on whether
167 * a whoami string was provided, error code is non-zero, and if a
168 * a 'while ...' messge was provided.
172 if ((!code
) && fmt
) {
174 fprintf(stderr
, my_gettext(MSG_WHILE
),
177 } else if (code
&& !fmt
) {
179 fprintf(stderr
, my_gettext(MSG_ERROR_MSG
),
180 error_message(code
));
182 } else if (code
&& fmt
) {
184 fprintf(stderr
, my_gettext(MSG_ERROR_MSG_WHILE
),
185 error_message(code
), whilebuf
);
191 if ((!code
) && fmt
) {
193 fprintf(stderr
, my_gettext(MSG_WHOAMI_WHILE
),
196 } else if (code
&& !fmt
) {
198 fprintf(stderr
, my_gettext(MSG_WHOAMI_ERROR_MSG
),
199 whoami
, error_message(code
));
201 } else if (code
&& fmt
) {
204 my_gettext(MSG_WHOAMI_ERROR_MSG_WHILE
),
205 whoami
, error_message(code
), whilebuf
);
209 my_gettext(MSG_WHOAMI
),
217 void KRB5_CALLCONV
com_err_va(const char *whoami
,
224 err
= com_err_finish_init();
227 err
= k5_mutex_lock(&com_err_hook_lock
);
230 for (i
= 0; i
< hook_count
; i
++) {
231 (com_err_hook
[i
])(whoami
, code
, fmt
, ap
);
233 k5_mutex_unlock(&com_err_hook_lock
);
237 /* Yikes. Our library initialization failed or we couldn't lock
238 the lock we want. We could be in trouble. Gosh, we should
239 probably print an error message. Oh, wait. That's what we're
240 trying to do. In fact, if we're losing on initialization here,
241 there's a good chance it has to do with failed initialization
244 for (i
= 0; i
< hook_count
; i
++) {
245 (com_err_hook
[i
])(whoami
, code
, fmt
, ap
);
252 void KRB5_CALLCONV_C
com_err(const char *whoami
,
254 const char *fmt
, ...)
259 com_err_va(whoami
, code
, fmt
, ap
);
263 /* Make a separate function because the assert invocations below
264 use the macro expansion on some platforms, which may be insanely
265 long and incomprehensible. */
266 static int com_err_lock_hook_handle(void)
268 return k5_mutex_lock(&com_err_hook_lock
);
271 et_old_error_hook_func
set_com_err_hook (et_old_error_hook_func new_proc
)
274 et_old_error_hook_func x
;
276 /* Broken initialization? What can we do? */
277 assert(com_err_finish_init() == 0);
278 assert(com_err_lock_hook_handle() == 0);
282 for (i
= 0; i
< hook_count
; i
++)
283 com_err_hook
[i
] = NULL
;
285 com_err_hook
[0] = new_proc
;
288 k5_mutex_unlock(&com_err_hook_lock
);
292 et_old_error_hook_func
reset_com_err_hook ()
295 et_old_error_hook_func x
;
297 /* Broken initialization? What can we do? */
298 assert(com_err_finish_init() == 0);
299 assert(com_err_lock_hook_handle() == 0);
301 for (i
= 0; i
< hook_count
; i
++)
302 com_err_hook
[i
] = NULL
;
304 com_err_hook
[0] = default_com_err_proc
;
306 k5_mutex_unlock(&com_err_hook_lock
);
312 * Register a hook which will be called every time
313 * com_err() is called.
315 void add_com_err_hook(et_old_error_hook_func f
) {
317 if (hook_count
< MAX_HOOKS
) {
318 for (i
= 0; i
< hook_count
; i
++) {
319 if (com_err_hook
[i
] == NULL
)
329 * Remove a logging hook. The first hook matching 'f' will
332 void rem_com_err_hook(et_old_error_hook_func f
) {
335 for (i
= 0; i
< hook_count
; i
++) {
336 if (com_err_hook
[i
] == f
) {
337 for (j
= i
; j
< hook_count
- 1; j
++) {
338 com_err_hook
[j
] = com_err_hook
[j
+1];
340 com_err_hook
[j
] = NULL
;
348 * Remove the default hook.
350 void rem_default_com_err_hook() {
351 rem_com_err_hook(default_com_err_proc
);
356 * Add back the default hook
358 void add_default_com_err_hook() {
359 add_com_err_hook(default_com_err_proc
);