xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/et/com_err.c (revision 7934:6aeeafc994de)
10Sstevel@tonic-gate /*
26426Smp153739  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate 
70Sstevel@tonic-gate /*
80Sstevel@tonic-gate  * Copyright 1997 by Massachusetts Institute of Technology
9*7934SMark.Phalan@Sun.COM  *
100Sstevel@tonic-gate  * Copyright 1987, 1988 by MIT Student Information Processing Board
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software
130Sstevel@tonic-gate  * and its documentation for any purpose and without fee is
140Sstevel@tonic-gate  * hereby granted, provided that the above copyright notice
150Sstevel@tonic-gate  * appear in all copies and that both that copyright notice and
160Sstevel@tonic-gate  * this permission notice appear in supporting documentation,
170Sstevel@tonic-gate  * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
180Sstevel@tonic-gate  * used in advertising or publicity pertaining to distribution
190Sstevel@tonic-gate  * of the software without specific, written prior permission.
200Sstevel@tonic-gate  * Furthermore if you modify this software you must label
210Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
220Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
230Sstevel@tonic-gate  * M.I.T. and the M.I.T. S.I.P.B. make no representations about
240Sstevel@tonic-gate  * the suitability of this software for any purpose.  It is
250Sstevel@tonic-gate  * provided "as is" without express or implied warranty.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <stdio.h>
290Sstevel@tonic-gate #include <string.h>
30*7934SMark.Phalan@Sun.COM #include <stdlib.h>
310Sstevel@tonic-gate #include <locale.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include "com_err.h"
340Sstevel@tonic-gate #include "error_table.h"
350Sstevel@tonic-gate 
36*7934SMark.Phalan@Sun.COM #if defined(_WIN32)
370Sstevel@tonic-gate #include <io.h>
380Sstevel@tonic-gate #endif
39*7934SMark.Phalan@Sun.COM 
40*7934SMark.Phalan@Sun.COM k5_mutex_t com_err_hook_lock = K5_MUTEX_PARTIAL_INITIALIZER;
410Sstevel@tonic-gate 
420Sstevel@tonic-gate static void default_com_err_proc
43781Sgtb (const char  *whoami, errcode_t code,
44781Sgtb 	const char  *fmt, va_list ap);
450Sstevel@tonic-gate 
46*7934SMark.Phalan@Sun.COM #if defined(_WIN32)
isGuiApp()47*7934SMark.Phalan@Sun.COM BOOL  isGuiApp() {
48*7934SMark.Phalan@Sun.COM 	DWORD mypid;
49*7934SMark.Phalan@Sun.COM 	HANDLE myprocess;
50*7934SMark.Phalan@Sun.COM 	mypid = GetCurrentProcessId();
51*7934SMark.Phalan@Sun.COM 	myprocess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, mypid);
52*7934SMark.Phalan@Sun.COM 	return GetGuiResources(myprocess, 1) > 0;
53*7934SMark.Phalan@Sun.COM 	}
54*7934SMark.Phalan@Sun.COM #endif
55*7934SMark.Phalan@Sun.COM 
566426Smp153739 /*
576426Smp153739  * Solaris Kerberos:
586426Smp153739  * It is sometimes desirable to have more than a single hook called
596426Smp153739  * when com_err() is invoked. A number of new functions have been
606426Smp153739  * added which allow hooks to be added and removed:
616426Smp153739  *    add_com_err_hook()
626426Smp153739  *    add_default_com_err_hook()
636426Smp153739  *    remove_com_err_hook()
646426Smp153739  *    remove_default_com_err_hook()
656426Smp153739  * The existing functions:
666426Smp153739  *    set_com_err_hook()
676426Smp153739  *    reset_com_err_hook()
686426Smp153739  *    com_err()
696426Smp153739  * have been modified to work with the new scheme. Applications using
706426Smp153739  * the original function calls are not affected.
716426Smp153739  */
726426Smp153739 #define	MAX_HOOKS 3
736426Smp153739 static et_old_error_hook_func com_err_hook[MAX_HOOKS] = { default_com_err_proc,
746426Smp153739     NULL, NULL };
756426Smp153739 static int hook_count = 1;
766426Smp153739 
770Sstevel@tonic-gate /* Solaris Kerberos specific fix start --------------------------- */
780Sstevel@tonic-gate 
790Sstevel@tonic-gate #define gettext(X)	X
800Sstevel@tonic-gate 
810Sstevel@tonic-gate struct msg_map {
820Sstevel@tonic-gate 	char *msgid;
830Sstevel@tonic-gate 	char *c_msgstr;
840Sstevel@tonic-gate };
850Sstevel@tonic-gate 
860Sstevel@tonic-gate struct msg_map msgmap[] = {
870Sstevel@tonic-gate 
880Sstevel@tonic-gate #define	MSG_WHILE 0
890Sstevel@tonic-gate 	{ gettext("%s\n## com_err msg of format: 'while ...'"),
900Sstevel@tonic-gate 		"%s\n" },
910Sstevel@tonic-gate 
920Sstevel@tonic-gate #define	MSG_ERROR_MSG 1
930Sstevel@tonic-gate 	{ gettext("%s\n## com_err message of format: 'error msg ...'"),
940Sstevel@tonic-gate 		"%s\n" },
950Sstevel@tonic-gate 
960Sstevel@tonic-gate #define	MSG_ERROR_MSG_WHILE 2
970Sstevel@tonic-gate 	{ gettext("%1$s %2$s\n## com_err message of format: "
980Sstevel@tonic-gate 		"'error msg ... while ...'"),
990Sstevel@tonic-gate 		"%1$s %2$s\n" },
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate #define	MSG_WHOAMI_WHILE 3
1020Sstevel@tonic-gate 	{ gettext("%1$s: %2$s\n## com_err msg of format: 'whoami: while ...'"),
1030Sstevel@tonic-gate 		"%1$s: %2$s\n" },
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate #define	MSG_WHOAMI_ERROR_MSG 4
1060Sstevel@tonic-gate 	{ gettext("%1$s: %2$s\n## com_err message of format: "
1070Sstevel@tonic-gate 		"'whoami: error msg ...'"),
1080Sstevel@tonic-gate 		"%1$s: %2$s\n" },
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate #define	MSG_WHOAMI_ERROR_MSG_WHILE 5
1110Sstevel@tonic-gate 	{ gettext("%1$s: %2$s %3$s\n## com_err message of format: "
1120Sstevel@tonic-gate 		"'whoami: error msg ... while ...'"),
1130Sstevel@tonic-gate 		"%1$s: %2$s %3$s\n" },
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate #define	MSG_WHOAMI 6
1160Sstevel@tonic-gate 	{ gettext("%s:\n ## com_err message of format: "
1170Sstevel@tonic-gate 		"'whoami: with no error msg or while ...'"),
1180Sstevel@tonic-gate 		"%s:\n " }
1190Sstevel@tonic-gate };
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate #undef gettext
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate /*
1240Sstevel@tonic-gate  * The idea is that we provide a unique message id that contains extra junk
1250Sstevel@tonic-gate  * that we never want to display in the C locale. If dgettext() returns
1260Sstevel@tonic-gate  * a string that is equal to the message id, then we return the c_msgstr,
1270Sstevel@tonic-gate  * for display in the locale.
1280Sstevel@tonic-gate  */
1290Sstevel@tonic-gate static char *
my_gettext(int msg_idx)1300Sstevel@tonic-gate my_gettext(int msg_idx)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate 	char *msgid = msgmap[msg_idx].msgid;
1330Sstevel@tonic-gate 	char *c_msgstr = msgmap[msg_idx].c_msgstr;
1340Sstevel@tonic-gate 	char *msgstr = dgettext(TEXT_DOMAIN, msgid);
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	if (strcmp(msgstr, msgid) == 0)
1370Sstevel@tonic-gate 		return (c_msgstr);
1380Sstevel@tonic-gate 	else
1390Sstevel@tonic-gate 		return (msgstr);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate /* Solaris Kerberos specific fix end --------------------------- */
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate /* Solaris Kerberos:  this code is significantly altered from
1450Sstevel@tonic-gate  * the MIT 1.2.1 version to work with internationalization */
146*7934SMark.Phalan@Sun.COM 
default_com_err_proc(const char * whoami,errcode_t code,const char * fmt,va_list ap)147*7934SMark.Phalan@Sun.COM static void default_com_err_proc (const char *whoami, errcode_t code,
148*7934SMark.Phalan@Sun.COM 				  const char *fmt, va_list ap)
1490Sstevel@tonic-gate {
1500Sstevel@tonic-gate 	char whilebuf[1024] = "";
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	*whilebuf = '\0';
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	/*
1550Sstevel@tonic-gate 	 * Because 'while ...' message could contain a format string
1560Sstevel@tonic-gate 	 * we have to intepret it now, in a buffer. We need to put it
1570Sstevel@tonic-gate 	 * into a buffer so that the message can be juxtaposed in a locale
1580Sstevel@tonic-gate 	 * meaningful manner. In some natural languages, the 'while ...' phrase
1590Sstevel@tonic-gate 	 * must be first.
1600Sstevel@tonic-gate 	 */
1610Sstevel@tonic-gate 	if (fmt) {
1620Sstevel@tonic-gate 		vsprintf(whilebuf, fmt, ap);
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	/*
1660Sstevel@tonic-gate 	 * There are 8 possible combinations here depending on whether
1670Sstevel@tonic-gate 	 * a whoami string was provided, error code is non-zero, and if a
1680Sstevel@tonic-gate 	 * a 'while ...' messge was provided.
1690Sstevel@tonic-gate 	 */
1700Sstevel@tonic-gate 	if (!whoami) {
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 		if ((!code) && fmt) {
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 			fprintf(stderr, my_gettext(MSG_WHILE),
1750Sstevel@tonic-gate 				whilebuf);
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 		} else if (code && !fmt) {
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 			fprintf(stderr, my_gettext(MSG_ERROR_MSG),
1800Sstevel@tonic-gate 				error_message(code));
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 		} else if (code && fmt) {
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 			fprintf(stderr, my_gettext(MSG_ERROR_MSG_WHILE),
1850Sstevel@tonic-gate 				error_message(code), whilebuf);
1860Sstevel@tonic-gate 		} else
1870Sstevel@tonic-gate 			return;
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	} else {
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 		if ((!code) && fmt) {
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 			fprintf(stderr, my_gettext(MSG_WHOAMI_WHILE),
1940Sstevel@tonic-gate 				whoami, whilebuf);
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 		} else if (code && !fmt) {
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 			fprintf(stderr, my_gettext(MSG_WHOAMI_ERROR_MSG),
1990Sstevel@tonic-gate 				whoami, error_message(code));
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 		} else if (code && fmt) {
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 			fprintf(stderr,
2040Sstevel@tonic-gate 				my_gettext(MSG_WHOAMI_ERROR_MSG_WHILE),
2050Sstevel@tonic-gate 				whoami, error_message(code), whilebuf);
2060Sstevel@tonic-gate 		} else {
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 			fprintf(stderr,
2090Sstevel@tonic-gate 				my_gettext(MSG_WHOAMI),
2100Sstevel@tonic-gate 				whoami);
2110Sstevel@tonic-gate 		}
2120Sstevel@tonic-gate 	}
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	fflush(stderr);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate 
com_err_va(const char * whoami,errcode_t code,const char * fmt,va_list ap)217*7934SMark.Phalan@Sun.COM void KRB5_CALLCONV com_err_va(const char *whoami,
218*7934SMark.Phalan@Sun.COM 			      errcode_t code,
219*7934SMark.Phalan@Sun.COM 			      const char *fmt,
220*7934SMark.Phalan@Sun.COM 			      va_list ap)
2210Sstevel@tonic-gate {
222*7934SMark.Phalan@Sun.COM     int err;
223*7934SMark.Phalan@Sun.COM     int i;
224*7934SMark.Phalan@Sun.COM     err = com_err_finish_init();
225*7934SMark.Phalan@Sun.COM     if (err)
226*7934SMark.Phalan@Sun.COM 	goto best_try;
227*7934SMark.Phalan@Sun.COM     err = k5_mutex_lock(&com_err_hook_lock);
228*7934SMark.Phalan@Sun.COM     if (err)
229*7934SMark.Phalan@Sun.COM 	goto best_try;
230*7934SMark.Phalan@Sun.COM     for (i = 0; i < hook_count; i++) {
231*7934SMark.Phalan@Sun.COM 	(com_err_hook[i])(whoami, code, fmt, ap);
232*7934SMark.Phalan@Sun.COM     }
233*7934SMark.Phalan@Sun.COM     k5_mutex_unlock(&com_err_hook_lock);
234*7934SMark.Phalan@Sun.COM     return;
2356426Smp153739 
236*7934SMark.Phalan@Sun.COM best_try:
237*7934SMark.Phalan@Sun.COM     /* Yikes.  Our library initialization failed or we couldn't lock
238*7934SMark.Phalan@Sun.COM        the lock we want.  We could be in trouble.  Gosh, we should
239*7934SMark.Phalan@Sun.COM        probably print an error message.  Oh, wait.  That's what we're
240*7934SMark.Phalan@Sun.COM        trying to do.  In fact, if we're losing on initialization here,
241*7934SMark.Phalan@Sun.COM        there's a good chance it has to do with failed initialization
242*7934SMark.Phalan@Sun.COM        of the caller.  */
243*7934SMark.Phalan@Sun.COM 
244*7934SMark.Phalan@Sun.COM     for (i = 0; i < hook_count; i++) {
245*7934SMark.Phalan@Sun.COM 	(com_err_hook[i])(whoami, code, fmt, ap);
246*7934SMark.Phalan@Sun.COM     }
247*7934SMark.Phalan@Sun.COM     assert(err == 0);
248*7934SMark.Phalan@Sun.COM     abort();
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 
com_err(const char * whoami,errcode_t code,const char * fmt,...)252*7934SMark.Phalan@Sun.COM void KRB5_CALLCONV_C com_err(const char *whoami,
253*7934SMark.Phalan@Sun.COM 			     errcode_t code,
254*7934SMark.Phalan@Sun.COM 			     const char *fmt, ...)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate 	va_list ap;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	va_start(ap, fmt);
2590Sstevel@tonic-gate 	com_err_va(whoami, code, fmt, ap);
2600Sstevel@tonic-gate 	va_end(ap);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate 
263*7934SMark.Phalan@Sun.COM /* Make a separate function because the assert invocations below
264*7934SMark.Phalan@Sun.COM    use the macro expansion on some platforms, which may be insanely
265*7934SMark.Phalan@Sun.COM    long and incomprehensible.  */
com_err_lock_hook_handle(void)266*7934SMark.Phalan@Sun.COM static int com_err_lock_hook_handle(void)
267*7934SMark.Phalan@Sun.COM {
268*7934SMark.Phalan@Sun.COM     return k5_mutex_lock(&com_err_hook_lock);
269*7934SMark.Phalan@Sun.COM }
270*7934SMark.Phalan@Sun.COM 
set_com_err_hook(et_old_error_hook_func new_proc)271*7934SMark.Phalan@Sun.COM et_old_error_hook_func set_com_err_hook (et_old_error_hook_func new_proc)
2720Sstevel@tonic-gate {
2736426Smp153739 	int i;
274*7934SMark.Phalan@Sun.COM 	et_old_error_hook_func x;
275*7934SMark.Phalan@Sun.COM 
276*7934SMark.Phalan@Sun.COM 	/* Broken initialization?  What can we do?  */
277*7934SMark.Phalan@Sun.COM 	assert(com_err_finish_init() == 0);
278*7934SMark.Phalan@Sun.COM 	assert(com_err_lock_hook_handle() == 0);
279*7934SMark.Phalan@Sun.COM 
280*7934SMark.Phalan@Sun.COM 	x = com_err_hook[0];
2810Sstevel@tonic-gate 
2826426Smp153739 	for (i = 0; i < hook_count; i++)
2836426Smp153739 		com_err_hook[i] = NULL;
2846426Smp153739 
2856426Smp153739 	com_err_hook[0] = new_proc;
2866426Smp153739 	hook_count = 1;
2876426Smp153739 
288*7934SMark.Phalan@Sun.COM 	k5_mutex_unlock(&com_err_hook_lock);
2890Sstevel@tonic-gate 	return x;
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate 
reset_com_err_hook()2920Sstevel@tonic-gate et_old_error_hook_func reset_com_err_hook ()
2930Sstevel@tonic-gate {
2946426Smp153739 	int i;
295*7934SMark.Phalan@Sun.COM 	et_old_error_hook_func x;
2960Sstevel@tonic-gate 
297*7934SMark.Phalan@Sun.COM 	/* Broken initialization?  What can we do?  */
298*7934SMark.Phalan@Sun.COM 	assert(com_err_finish_init() == 0);
299*7934SMark.Phalan@Sun.COM 	assert(com_err_lock_hook_handle() == 0);
300*7934SMark.Phalan@Sun.COM 	x = com_err_hook[0];
3016426Smp153739 	for (i = 0; i < hook_count; i++)
3026426Smp153739 		com_err_hook[i] = NULL;
3036426Smp153739 
3046426Smp153739 	com_err_hook[0] = default_com_err_proc;
3056426Smp153739 	hook_count = 1;
306*7934SMark.Phalan@Sun.COM 	k5_mutex_unlock(&com_err_hook_lock);
3070Sstevel@tonic-gate 	return x;
3080Sstevel@tonic-gate }
3096426Smp153739 
3106426Smp153739 /*
3116426Smp153739  * Solaris Kerberos:
3126426Smp153739  * Register a hook which will be called every time
3136426Smp153739  * com_err() is called.
3146426Smp153739  */
add_com_err_hook(et_old_error_hook_func f)3156426Smp153739 void add_com_err_hook(et_old_error_hook_func f) {
3166426Smp153739 	int i;
3176426Smp153739 	if (hook_count < MAX_HOOKS) {
3186426Smp153739 		for (i = 0; i < hook_count; i++) {
3196426Smp153739 			if (com_err_hook[i] == NULL)
3206426Smp153739 				break;
3216426Smp153739 		}
3226426Smp153739 		com_err_hook[i] = f;
3236426Smp153739 		hook_count++;
3246426Smp153739 	}
3256426Smp153739 }
3266426Smp153739 
3276426Smp153739 /*
3286426Smp153739  * Solaris Kerberos:
3296426Smp153739  * Remove a logging hook. The first hook matching 'f' will
3306426Smp153739  * be removed.
3316426Smp153739  */
rem_com_err_hook(et_old_error_hook_func f)3326426Smp153739 void rem_com_err_hook(et_old_error_hook_func f) {
3336426Smp153739 	int i, j;
3346426Smp153739 
3356426Smp153739 	for (i = 0; i < hook_count; i++) {
3366426Smp153739 		if (com_err_hook[i] == f) {
3376426Smp153739 			for (j = i; j < hook_count - 1; j++) {
3386426Smp153739 				com_err_hook[j] = com_err_hook[j+1];
3396426Smp153739 			}
3406426Smp153739 			com_err_hook[j] = NULL;
3416426Smp153739 			hook_count--;
3426426Smp153739 		}
3436426Smp153739 	}
3446426Smp153739 }
3456426Smp153739 
3466426Smp153739 /*
3476426Smp153739  * Solaris Kerberos:
3486426Smp153739  * Remove the default hook.
3496426Smp153739  */
rem_default_com_err_hook()3506426Smp153739 void rem_default_com_err_hook() {
3516426Smp153739 	rem_com_err_hook(default_com_err_proc);
3526426Smp153739 }
3536426Smp153739 
3546426Smp153739 /*
3556426Smp153739  * Solaris Kerberos:
3566426Smp153739  * Add back the default hook
3576426Smp153739  */
add_default_com_err_hook()3586426Smp153739 void add_default_com_err_hook() {
3596426Smp153739 	add_com_err_hook(default_com_err_proc);
3606426Smp153739 }
361