1 /* 2 * Copyright 2008 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 void default_com_err_proc 46 (const char *whoami, errcode_t code, 47 const char *fmt, va_list ap); 48 49 /* 50 * Solaris Kerberos: 51 * It is sometimes desirable to have more than a single hook called 52 * when com_err() is invoked. A number of new functions have been 53 * added which allow hooks to be added and removed: 54 * add_com_err_hook() 55 * add_default_com_err_hook() 56 * remove_com_err_hook() 57 * remove_default_com_err_hook() 58 * The existing functions: 59 * set_com_err_hook() 60 * reset_com_err_hook() 61 * com_err() 62 * have been modified to work with the new scheme. Applications using 63 * the original function calls are not affected. 64 */ 65 #define MAX_HOOKS 3 66 static et_old_error_hook_func com_err_hook[MAX_HOOKS] = { default_com_err_proc, 67 NULL, NULL }; 68 static int hook_count = 1; 69 70 /* Solaris Kerberos specific fix start --------------------------- */ 71 72 #define gettext(X) X 73 74 struct msg_map { 75 char *msgid; 76 char *c_msgstr; 77 }; 78 79 struct msg_map msgmap[] = { 80 81 #define MSG_WHILE 0 82 { gettext("%s\n## com_err msg of format: 'while ...'"), 83 "%s\n" }, 84 85 #define MSG_ERROR_MSG 1 86 { gettext("%s\n## com_err message of format: 'error msg ...'"), 87 "%s\n" }, 88 89 #define MSG_ERROR_MSG_WHILE 2 90 { gettext("%1$s %2$s\n## com_err message of format: " 91 "'error msg ... while ...'"), 92 "%1$s %2$s\n" }, 93 94 #define MSG_WHOAMI_WHILE 3 95 { gettext("%1$s: %2$s\n## com_err msg of format: 'whoami: while ...'"), 96 "%1$s: %2$s\n" }, 97 98 #define MSG_WHOAMI_ERROR_MSG 4 99 { gettext("%1$s: %2$s\n## com_err message of format: " 100 "'whoami: error msg ...'"), 101 "%1$s: %2$s\n" }, 102 103 #define MSG_WHOAMI_ERROR_MSG_WHILE 5 104 { gettext("%1$s: %2$s %3$s\n## com_err message of format: " 105 "'whoami: error msg ... while ...'"), 106 "%1$s: %2$s %3$s\n" }, 107 108 #define MSG_WHOAMI 6 109 { gettext("%s:\n ## com_err message of format: " 110 "'whoami: with no error msg or while ...'"), 111 "%s:\n " } 112 }; 113 114 #undef gettext 115 116 /* 117 * The idea is that we provide a unique message id that contains extra junk 118 * that we never want to display in the C locale. If dgettext() returns 119 * a string that is equal to the message id, then we return the c_msgstr, 120 * for display in the locale. 121 */ 122 static char * 123 my_gettext(int msg_idx) 124 { 125 char *msgid = msgmap[msg_idx].msgid; 126 char *c_msgstr = msgmap[msg_idx].c_msgstr; 127 char *msgstr = dgettext(TEXT_DOMAIN, msgid); 128 129 if (strcmp(msgstr, msgid) == 0) 130 return (c_msgstr); 131 else 132 return (msgstr); 133 } 134 135 /* Solaris Kerberos specific fix end --------------------------- */ 136 137 /* Solaris Kerberos: this code is significantly altered from 138 * the MIT 1.2.1 version to work with internationalization */ 139 static void default_com_err_proc(whoami, code, fmt, ap) 140 const char *whoami; 141 errcode_t code; 142 const char *fmt; 143 va_list ap; 144 { 145 char whilebuf[1024] = ""; 146 147 *whilebuf = '\0'; 148 149 /* 150 * Because 'while ...' message could contain a format string 151 * we have to intepret it now, in a buffer. We need to put it 152 * into a buffer so that the message can be juxtaposed in a locale 153 * meaningful manner. In some natural languages, the 'while ...' phrase 154 * must be first. 155 */ 156 if (fmt) { 157 vsprintf(whilebuf, fmt, ap); 158 } 159 160 /* 161 * There are 8 possible combinations here depending on whether 162 * a whoami string was provided, error code is non-zero, and if a 163 * a 'while ...' messge was provided. 164 */ 165 if (!whoami) { 166 167 if ((!code) && fmt) { 168 169 fprintf(stderr, my_gettext(MSG_WHILE), 170 whilebuf); 171 172 } else if (code && !fmt) { 173 174 fprintf(stderr, my_gettext(MSG_ERROR_MSG), 175 error_message(code)); 176 177 } else if (code && fmt) { 178 179 fprintf(stderr, my_gettext(MSG_ERROR_MSG_WHILE), 180 error_message(code), whilebuf); 181 } else 182 return; 183 184 } else { 185 186 if ((!code) && fmt) { 187 188 fprintf(stderr, my_gettext(MSG_WHOAMI_WHILE), 189 whoami, whilebuf); 190 191 } else if (code && !fmt) { 192 193 fprintf(stderr, my_gettext(MSG_WHOAMI_ERROR_MSG), 194 whoami, error_message(code)); 195 196 } else if (code && fmt) { 197 198 fprintf(stderr, 199 my_gettext(MSG_WHOAMI_ERROR_MSG_WHILE), 200 whoami, error_message(code), whilebuf); 201 } else { 202 203 fprintf(stderr, 204 my_gettext(MSG_WHOAMI), 205 whoami); 206 } 207 } 208 209 fflush(stderr); 210 } 211 212 void KRB5_CALLCONV com_err_va(whoami, code, fmt, ap) 213 const char *whoami; 214 errcode_t code; 215 const char *fmt; 216 va_list ap; 217 { 218 int i; 219 220 for (i = 0; i < hook_count; i++) { 221 (com_err_hook[i])(whoami, code, fmt, ap); 222 } 223 } 224 225 226 #ifndef ET_VARARGS 227 void KRB5_CALLCONV_C com_err(const char *whoami, 228 errcode_t code, 229 const char *fmt, ...) 230 #else 231 void KRB5_CALLCONV_C com_err(whoami, code, fmt, va_alist) 232 const char *whoami; 233 errcode_t code; 234 const char *fmt; 235 va_dcl 236 #endif 237 { 238 va_list ap; 239 240 #ifdef ET_VARARGS 241 va_start(ap); 242 #else 243 va_start(ap, fmt); 244 #endif 245 com_err_va(whoami, code, fmt, ap); 246 va_end(ap); 247 } 248 249 #if !(defined(_MSDOS)||defined(_WIN32)) 250 et_old_error_hook_func set_com_err_hook (new_proc) 251 et_old_error_hook_func new_proc; 252 { 253 int i; 254 et_old_error_hook_func x = com_err_hook[0]; 255 256 for (i = 0; i < hook_count; i++) 257 com_err_hook[i] = NULL; 258 259 com_err_hook[0] = new_proc; 260 hook_count = 1; 261 262 return x; 263 } 264 265 et_old_error_hook_func reset_com_err_hook () 266 { 267 int i; 268 et_old_error_hook_func x = com_err_hook[0]; 269 270 for (i = 0; i < hook_count; i++) 271 com_err_hook[i] = NULL; 272 273 com_err_hook[0] = default_com_err_proc; 274 hook_count = 1; 275 276 return x; 277 } 278 #endif 279 280 /* 281 * Solaris Kerberos: 282 * Register a hook which will be called every time 283 * com_err() is called. 284 */ 285 void add_com_err_hook(et_old_error_hook_func f) { 286 int i; 287 if (hook_count < MAX_HOOKS) { 288 for (i = 0; i < hook_count; i++) { 289 if (com_err_hook[i] == NULL) 290 break; 291 } 292 com_err_hook[i] = f; 293 hook_count++; 294 } 295 } 296 297 /* 298 * Solaris Kerberos: 299 * Remove a logging hook. The first hook matching 'f' will 300 * be removed. 301 */ 302 void rem_com_err_hook(et_old_error_hook_func f) { 303 int i, j; 304 305 for (i = 0; i < hook_count; i++) { 306 if (com_err_hook[i] == f) { 307 for (j = i; j < hook_count - 1; j++) { 308 com_err_hook[j] = com_err_hook[j+1]; 309 } 310 com_err_hook[j] = NULL; 311 hook_count--; 312 } 313 } 314 } 315 316 /* 317 * Solaris Kerberos: 318 * Remove the default hook. 319 */ 320 void rem_default_com_err_hook() { 321 rem_com_err_hook(default_com_err_proc); 322 } 323 324 /* 325 * Solaris Kerberos: 326 * Add back the default hook 327 */ 328 void add_default_com_err_hook() { 329 add_com_err_hook(default_com_err_proc); 330 } 331