nwrap: Fix resolving hostnames with a trailing dot.
[sfrench/samba-autobuild/.git] / lib / util / fault.c
1 /*
2    Unix SMB/CIFS implementation.
3    Critical Fault handling
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Tim Prouty 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "replace.h"
22 #include "system/filesys.h"
23 #include "system/wait.h"
24 #include "version.h"
25
26 #ifdef HAVE_SYS_SYSCTL_H
27 #include <sys/sysctl.h>
28 #endif
29
30
31 #ifdef HAVE_SYS_PRCTL_H
32 #include <sys/prctl.h>
33 #endif
34
35 #include "debug.h"
36 #include "lib/util/signal.h" /* Avoid /usr/include/signal.h */
37 #include "substitute.h"
38 #include "fault.h"
39
40 static struct {
41         bool disabled;
42         smb_panic_handler_t panic_handler;
43 } fault_state;
44
45
46 /*******************************************************************
47 setup variables used for fault handling
48 ********************************************************************/
49 void fault_configure(smb_panic_handler_t panic_handler)
50 {
51         fault_state.panic_handler = panic_handler;
52 }
53
54
55 /**
56    disable setting up fault handlers
57    This is used for the bind9 dlz module, as we
58    don't want a Samba module in bind9 to override the bind
59    fault handling
60 **/
61 _PUBLIC_ void fault_setup_disable(void)
62 {
63         fault_state.disabled = true;
64 }
65
66
67 /*******************************************************************
68 report a fault
69 ********************************************************************/
70 static void fault_report(int sig)
71 {
72         static int counter;
73
74         if (counter) _exit(1);
75
76         counter++;
77
78         DEBUGSEP(0);
79         DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),SAMBA_VERSION_STRING));
80         DEBUG(0,("\nPlease read the Trouble-Shooting section of the Samba HOWTO\n"));
81         DEBUGSEP(0);
82
83         smb_panic("internal error");
84
85         /* smb_panic() never returns, so this is really redundant */
86         exit(1);
87 }
88
89 /****************************************************************************
90 catch serious errors
91 ****************************************************************************/
92 static void sig_fault(int sig)
93 {
94         fault_report(sig);
95 }
96
97 /*******************************************************************
98 setup our fault handlers
99 ********************************************************************/
100 void fault_setup(void)
101 {
102         if (fault_state.disabled) {
103                 return;
104         }
105 #if !defined(HAVE_DISABLE_FAULT_HANDLING)
106 #ifdef SIGSEGV
107         CatchSignal(SIGSEGV, sig_fault);
108 #endif
109 #ifdef SIGBUS
110         CatchSignal(SIGBUS, sig_fault);
111 #endif
112 #ifdef SIGABRT
113         CatchSignal(SIGABRT, sig_fault);
114 #endif
115 #endif
116 }
117
118 _PUBLIC_ const char *panic_action = NULL;
119
120 /*
121    default smb_panic() implementation
122 */
123 static void smb_panic_default(const char *why) _NORETURN_;
124 static void smb_panic_default(const char *why)
125 {
126 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
127         /*
128          * Make sure all children can attach a debugger.
129          */
130         prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
131 #endif
132
133         if (panic_action && *panic_action) {
134                 char cmdstring[200];
135                 if (strlcpy(cmdstring, panic_action, sizeof(cmdstring)) < sizeof(cmdstring)) {
136                         int result;
137                         char pidstr[20];
138                         snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid());
139                         all_string_sub(cmdstring, "%d", pidstr, sizeof(cmdstring));
140                         DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmdstring));
141                         result = system(cmdstring);
142
143                         if (result == -1)
144                                 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
145                                           strerror(errno)));
146                         else
147                                 DEBUG(0, ("smb_panic(): action returned status %d\n",
148                                           WEXITSTATUS(result)));
149                 }
150         }
151         DEBUG(0,("PANIC: %s\n", why));
152
153 #ifdef SIGABRT
154         CatchSignal(SIGABRT, SIG_DFL);
155 #endif
156         abort();
157 }
158
159
160 /**
161    Something really nasty happened - panic !
162 **/
163 _PUBLIC_ void smb_panic(const char *why)
164 {
165         if (fault_state.panic_handler) {
166                 fault_state.panic_handler(why);
167                 _exit(1);
168         }
169         smb_panic_default(why);
170 }