xref: /freebsd/crypto/krb5/src/util/et/com_err.c (revision 24e4dcf4ba5e9dedcf89efd358ea3e1fe5867020)
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