1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 1997 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 <stdio.h> 24 #include <string.h> 25 #include <stdlib.h> 26 27 #include "com_err.h" 28 #include "error_table.h" 29 30 #if defined(_WIN32) 31 #include <io.h> 32 #endif 33 34 static /*@null@*/ et_old_error_hook_func com_err_hook = 0; 35 k5_mutex_t com_err_hook_lock = K5_MUTEX_PARTIAL_INITIALIZER; 36 37 #if defined(_WIN32) 38 BOOL isGuiApp(void) { 39 DWORD mypid; 40 HANDLE myprocess; 41 mypid = GetCurrentProcessId(); 42 myprocess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, mypid); 43 return GetGuiResources(myprocess, 1) > 0; 44 } 45 #endif 46 47 static void default_com_err_proc (const char *whoami, errcode_t code, 48 const char *fmt, va_list ap) 49 { 50 #if defined(_WIN32) 51 52 char errbuf[1024] = ""; 53 54 if (whoami) { 55 errbuf[sizeof(errbuf) - 1] = '\0'; 56 strncat (errbuf, whoami, sizeof(errbuf) - 1 - strlen(errbuf)); 57 strncat (errbuf, ": ", sizeof(errbuf) - 1 - strlen(errbuf)); 58 } 59 if (code) { 60 errbuf[sizeof(errbuf) - 1] = '\0'; 61 strncat (errbuf, error_message(code), sizeof(errbuf) - 1 - strlen(errbuf)); 62 strncat (errbuf, " ", sizeof(errbuf) - 1 - strlen(errbuf)); 63 } 64 if (fmt) 65 /* ITS4: ignore vsprintf */ 66 vsprintf (errbuf + strlen (errbuf), fmt, ap); 67 errbuf[sizeof(errbuf) - 1] = '\0'; 68 69 if (_isatty(_fileno(stderr)) || !isGuiApp()) { 70 fputs(errbuf, stderr); 71 fputc('\r', stderr); 72 fputc('\n', stderr); 73 fflush(stderr); 74 } else 75 MessageBox ((HWND)NULL, errbuf, "Kerberos", MB_ICONEXCLAMATION); 76 77 #else /* !_WIN32 */ 78 79 if (whoami) { 80 fputs(whoami, stderr); 81 fputs(": ", stderr); 82 } 83 if (code) { 84 fputs(error_message(code), stderr); 85 fputs(" ", stderr); 86 } 87 if (fmt) { 88 vfprintf(stderr, fmt, ap); 89 } 90 /* should do this only on a tty in raw mode */ 91 putc('\r', stderr); 92 putc('\n', stderr); 93 fflush(stderr); 94 95 #endif 96 } 97 98 void KRB5_CALLCONV com_err_va(const char *whoami, 99 errcode_t code, 100 const char *fmt, 101 va_list ap) 102 { 103 int err; 104 et_old_error_hook_func p; 105 106 err = com_err_finish_init(); 107 if (err) 108 goto best_try; 109 k5_mutex_lock(&com_err_hook_lock); 110 p = com_err_hook ? com_err_hook : default_com_err_proc; 111 (*p)(whoami, code, fmt, ap); 112 k5_mutex_unlock(&com_err_hook_lock); 113 return; 114 115 best_try: 116 /* Yikes. Our library initialization failed or we couldn't lock 117 the lock we want. We could be in trouble. Gosh, we should 118 probably print an error message. Oh, wait. That's what we're 119 trying to do. In fact, if we're losing on initialization here, 120 there's a good chance it has to do with failed initialization 121 of the caller. */ 122 if (!com_err_hook) 123 default_com_err_proc(whoami, code, fmt, ap); 124 else 125 (com_err_hook)(whoami, code, fmt, ap); 126 assert(err == 0); 127 abort(); 128 } 129 130 131 void KRB5_CALLCONV_C com_err(const char *whoami, 132 errcode_t code, 133 const char *fmt, ...) 134 { 135 va_list ap; 136 137 va_start(ap, fmt); 138 com_err_va(whoami, code, fmt, ap); 139 va_end(ap); 140 } 141 142 /* Make a separate function because the assert invocations below 143 use the macro expansion on some platforms, which may be insanely 144 long and incomprehensible. */ 145 static void com_err_lock_hook_handle(void) 146 { 147 k5_mutex_lock(&com_err_hook_lock); 148 } 149 150 et_old_error_hook_func set_com_err_hook (et_old_error_hook_func new_proc) 151 { 152 et_old_error_hook_func x; 153 154 /* Broken initialization? What can we do? */ 155 if (com_err_finish_init() != 0) 156 abort(); 157 com_err_lock_hook_handle(); 158 x = com_err_hook; 159 com_err_hook = new_proc; 160 k5_mutex_unlock(&com_err_hook_lock); 161 return x; 162 } 163 164 et_old_error_hook_func reset_com_err_hook (void) 165 { 166 et_old_error_hook_func x; 167 168 /* Broken initialization? What can we do? */ 169 if (com_err_finish_init() != 0) 170 abort(); 171 com_err_lock_hook_handle(); 172 x = com_err_hook; 173 com_err_hook = NULL; 174 k5_mutex_unlock(&com_err_hook_lock); 175 return x; 176 } 177