1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * Copyright 1997 by Massachusetts Institute of Technology
10  *
11  * Copyright 1987, 1988 by MIT Student Information Processing Board
12  *
13  * Permission to use, copy, modify, and distribute this software
14  * and its documentation for any purpose and without fee is
15  * hereby granted, provided that the above copyright notice
16  * appear in all copies and that both that copyright notice and
17  * this permission notice appear in supporting documentation,
18  * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
19  * used in advertising or publicity pertaining to distribution
20  * of the software without specific, written prior permission.
21  * Furthermore if you modify this software you must label
22  * your software as modified software and not distribute it in such a
23  * fashion that it might be confused with the original M.I.T. software.
24  * M.I.T. and the M.I.T. S.I.P.B. make no representations about
25  * the suitability of this software for any purpose.  It is
26  * provided "as is" without express or implied warranty.
27  */
28 
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <locale.h>
33 
34 #include "com_err.h"
35 #include "error_table.h"
36 
37 #if defined(_MSDOS) || defined(_WIN32)
38 #include <io.h>
39 #endif
40 #ifdef macintosh
41 #include "icons.h"
42 static void MacMessageBox(char *errbuf);
43 #endif
44 
45 static et_old_error_hook_func com_err_hook = 0;
46 
47 static void default_com_err_proc
48 (const char  *whoami, errcode_t code,
49 	const char  *fmt, va_list ap);
50 
51 /* Solaris Kerberos specific fix start --------------------------- */
52 
53 #define gettext(X)	X
54 
55 struct msg_map {
56 	char *msgid;
57 	char *c_msgstr;
58 };
59 
60 struct msg_map msgmap[] = {
61 
62 #define	MSG_WHILE 0
63 	{ gettext("%s\n## com_err msg of format: 'while ...'"),
64 		"%s\n" },
65 
66 #define	MSG_ERROR_MSG 1
67 	{ gettext("%s\n## com_err message of format: 'error msg ...'"),
68 		"%s\n" },
69 
70 #define	MSG_ERROR_MSG_WHILE 2
71 	{ gettext("%1$s %2$s\n## com_err message of format: "
72 		"'error msg ... while ...'"),
73 		"%1$s %2$s\n" },
74 
75 #define	MSG_WHOAMI_WHILE 3
76 	{ gettext("%1$s: %2$s\n## com_err msg of format: 'whoami: while ...'"),
77 		"%1$s: %2$s\n" },
78 
79 #define	MSG_WHOAMI_ERROR_MSG 4
80 	{ gettext("%1$s: %2$s\n## com_err message of format: "
81 		"'whoami: error msg ...'"),
82 		"%1$s: %2$s\n" },
83 
84 #define	MSG_WHOAMI_ERROR_MSG_WHILE 5
85 	{ gettext("%1$s: %2$s %3$s\n## com_err message of format: "
86 		"'whoami: error msg ... while ...'"),
87 		"%1$s: %2$s %3$s\n" },
88 
89 #define	MSG_WHOAMI 6
90 	{ gettext("%s:\n ## com_err message of format: "
91 		"'whoami: with no error msg or while ...'"),
92 		"%s:\n " }
93 };
94 
95 #undef gettext
96 
97 /*
98  * The idea is that we provide a unique message id that contains extra junk
99  * that we never want to display in the C locale. If dgettext() returns
100  * a string that is equal to the message id, then we return the c_msgstr,
101  * for display in the locale.
102  */
103 static char *
104 my_gettext(int msg_idx)
105 {
106 	char *msgid = msgmap[msg_idx].msgid;
107 	char *c_msgstr = msgmap[msg_idx].c_msgstr;
108 	char *msgstr = dgettext(TEXT_DOMAIN, msgid);
109 
110 	if (strcmp(msgstr, msgid) == 0)
111 		return (c_msgstr);
112 	else
113 		return (msgstr);
114 }
115 
116 /* Solaris Kerberos specific fix end --------------------------- */
117 
118 /* Solaris Kerberos:  this code is significantly altered from
119  * the MIT 1.2.1 version to work with internationalization */
120 static void default_com_err_proc(whoami, code, fmt, ap)
121 	const char  *whoami;
122 	errcode_t code;
123 	const char  *fmt;
124 	va_list ap;
125 {
126 	char whilebuf[1024] = "";
127 
128 	*whilebuf = '\0';
129 
130 	/*
131 	 * Because 'while ...' message could contain a format string
132 	 * we have to intepret it now, in a buffer. We need to put it
133 	 * into a buffer so that the message can be juxtaposed in a locale
134 	 * meaningful manner. In some natural languages, the 'while ...' phrase
135 	 * must be first.
136 	 */
137 	if (fmt) {
138 		vsprintf(whilebuf, fmt, ap);
139 	}
140 
141 	/*
142 	 * There are 8 possible combinations here depending on whether
143 	 * a whoami string was provided, error code is non-zero, and if a
144 	 * a 'while ...' messge was provided.
145 	 */
146 	if (!whoami) {
147 
148 		if ((!code) && fmt) {
149 
150 			fprintf(stderr, my_gettext(MSG_WHILE),
151 				whilebuf);
152 
153 		} else if (code && !fmt) {
154 
155 			fprintf(stderr, my_gettext(MSG_ERROR_MSG),
156 				error_message(code));
157 
158 		} else if (code && fmt) {
159 
160 			fprintf(stderr, my_gettext(MSG_ERROR_MSG_WHILE),
161 				error_message(code), whilebuf);
162 		} else
163 			return;
164 
165 	} else {
166 
167 		if ((!code) && fmt) {
168 
169 			fprintf(stderr, my_gettext(MSG_WHOAMI_WHILE),
170 				whoami, whilebuf);
171 
172 		} else if (code && !fmt) {
173 
174 			fprintf(stderr, my_gettext(MSG_WHOAMI_ERROR_MSG),
175 				whoami, error_message(code));
176 
177 		} else if (code && fmt) {
178 
179 			fprintf(stderr,
180 				my_gettext(MSG_WHOAMI_ERROR_MSG_WHILE),
181 				whoami, error_message(code), whilebuf);
182 		} else {
183 
184 			fprintf(stderr,
185 				my_gettext(MSG_WHOAMI),
186 				whoami);
187 		}
188 	}
189 
190 	fflush(stderr);
191 }
192 
193 void KRB5_CALLCONV com_err_va(whoami, code, fmt, ap)
194 	const char  *whoami;
195 	errcode_t code;
196 	const char  *fmt;
197 	va_list ap;
198 {
199 	if (!com_err_hook)
200 		default_com_err_proc(whoami, code, fmt, ap);
201 	else
202 	  (com_err_hook)(whoami, code, fmt, ap);
203 }
204 
205 
206 #ifndef ET_VARARGS
207 void KRB5_CALLCONV_C com_err(const char  *whoami,
208 					 errcode_t code,
209 					 const char  *fmt, ...)
210 #else
211 void KRB5_CALLCONV_C com_err(whoami, code, fmt, va_alist)
212 	const char  *whoami;
213 	errcode_t code;
214 	const char  *fmt;
215 	va_dcl
216 #endif
217 {
218 	va_list ap;
219 
220 #ifdef ET_VARARGS
221 	va_start(ap);
222 #else
223 	va_start(ap, fmt);
224 #endif
225 	com_err_va(whoami, code, fmt, ap);
226 	va_end(ap);
227 }
228 
229 #if !(defined(_MSDOS)||defined(_WIN32))
230 et_old_error_hook_func set_com_err_hook (new_proc)
231 	et_old_error_hook_func new_proc;
232 {
233 	et_old_error_hook_func x = com_err_hook;
234 
235 	com_err_hook = new_proc;
236 	return x;
237 }
238 
239 et_old_error_hook_func reset_com_err_hook ()
240 {
241 	et_old_error_hook_func x = com_err_hook;
242 
243 	com_err_hook = 0;
244 	return x;
245 }
246 #endif
247