]>
Commit | Line | Data |
---|---|---|
70482933 RK |
1 | /**************************************************************************** |
2 | * * | |
3 | * GNAT COMPILER COMPONENTS * | |
4 | * * | |
fbf5a39b | 5 | * C T R L _ C * |
70482933 RK |
6 | * * |
7 | * C Implementation File * | |
8 | * * | |
4b490c1e | 9 | * Copyright (C) 2002-2020, Free Software Foundation, Inc. * |
70482933 RK |
10 | * * |
11 | * GNAT is free software; you can redistribute it and/or modify it under * | |
12 | * terms of the GNU General Public License as published by the Free Soft- * | |
748086b7 | 13 | * ware Foundation; either version 3, or (at your option) any later ver- * |
70482933 RK |
14 | * sion. GNAT is distributed in the hope that it will be useful, but WITH- * |
15 | * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * | |
748086b7 JJ |
16 | * or FITNESS FOR A PARTICULAR PURPOSE. * |
17 | * * | |
18 | * As a special exception under Section 7 of GPL version 3, you are granted * | |
19 | * additional permissions described in the GCC Runtime Library Exception, * | |
20 | * version 3.1, as published by the Free Software Foundation. * | |
21 | * * | |
22 | * You should have received a copy of the GNU General Public License and * | |
23 | * a copy of the GCC Runtime Library Exception along with this program; * | |
24 | * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see * | |
25 | * <http://www.gnu.org/licenses/>. * | |
70482933 RK |
26 | * * |
27 | * GNAT was originally developed by the GNAT team at New York University. * | |
71ff80dc | 28 | * Extensive contributions were provided by Ada Core Technologies Inc. * |
70482933 RK |
29 | * * |
30 | ****************************************************************************/ | |
31 | ||
a6fc663e | 32 | #ifndef IN_RTS |
70482933 RK |
33 | #include "config.h" |
34 | #include "system.h" | |
35 | #endif | |
36 | ||
fbf5a39b AC |
37 | /* Services to intercept Ctrl-C */ |
38 | ||
39 | /* __gnat_install_int_handler will install the specified handler. | |
40 | If called for the first time, it will also save the original handler */ | |
41 | void __gnat_install_int_handler (void (*) (void)); | |
42 | ||
43 | /* __gnat_uninstall_int_handler will reinstall the original handler */ | |
44 | void __gnat_uninstall_int_handler (void); | |
45 | ||
fbf5a39b AC |
46 | /* POSIX implementation */ |
47 | ||
2fe53bf5 | 48 | #if (defined (__unix__) || defined (_AIX) || defined (__APPLE__)) \ |
4bc0cadd AC |
49 | || defined (VMS) && !defined (__vxworks) |
50 | ||
51 | #ifdef VMS | |
52 | /* On VMS _gnat_handle_vms_condition gets control first, and it has to | |
53 | resignal the Ctrl/C in order for sigaction to gain control and execute | |
54 | the user handler routine, but in doing so propagates the condition | |
55 | causing the program to terminate. So instead we install a dummy handler | |
56 | routine and put the real user handler in a special global variable so | |
57 | that __gnat_handle_vms_condition can declare an AST to asynchronously | |
58 | execute the Ctrl/C user handler at some future time and allow | |
59 | __gnat_handle_vms_condition to return and not be held up waiting for | |
60 | the potentially unbounded time required to execute the Crtl/C handler. */ | |
61 | void | |
62 | dummy_handler () {} | |
63 | ||
64 | /* Lives in init.c. */ | |
65 | extern void (*__gnat_ctrl_c_handler) (void); | |
66 | #endif | |
fbf5a39b AC |
67 | |
68 | #include <signal.h> | |
69 | ||
70 | void (*sigint_intercepted) (void) = 0; | |
71 | ||
72 | struct sigaction original_act; | |
73 | ||
74 | static void | |
75 | __gnat_int_handler (int sig __attribute__ ((unused))) | |
76 | { | |
77 | if (sigint_intercepted != 0) | |
78 | sigint_intercepted (); | |
79 | } | |
80 | ||
81 | /* Install handler and save original handler. */ | |
70482933 | 82 | |
fbf5a39b AC |
83 | void |
84 | __gnat_install_int_handler (void (*proc) (void)) | |
85 | { | |
86 | struct sigaction act; | |
87 | ||
88 | if (sigint_intercepted == 0) | |
89 | { | |
90 | act.sa_handler = __gnat_int_handler; | |
4f100fd7 AP |
91 | #if defined (__Lynx__) || defined (VMS) || defined(__DJGPP__) |
92 | /* LynxOS, VMS and DJGPP do not support SA_RESTART. */ | |
2fe53bf5 EB |
93 | act.sa_flags = 0; |
94 | #else | |
fbf5a39b | 95 | act.sa_flags = SA_RESTART; |
2fe53bf5 | 96 | #endif |
fbf5a39b AC |
97 | sigemptyset (&act.sa_mask); |
98 | sigaction (SIGINT, &act, &original_act); | |
99 | } | |
100 | ||
4bc0cadd AC |
101 | #ifdef VMS |
102 | sigint_intercepted = &dummy_handler; | |
103 | __gnat_ctrl_c_handler = proc; | |
104 | #else | |
fbf5a39b | 105 | sigint_intercepted = proc; |
4bc0cadd | 106 | #endif |
fbf5a39b AC |
107 | } |
108 | ||
109 | /* Restore original handler */ | |
70482933 RK |
110 | |
111 | void | |
fbf5a39b | 112 | __gnat_uninstall_int_handler (void) |
70482933 | 113 | { |
fbf5a39b AC |
114 | if (sigint_intercepted != 0) |
115 | { | |
116 | sigaction (SIGINT, &original_act, 0); | |
117 | sigint_intercepted = 0; | |
118 | } | |
4bc0cadd AC |
119 | #ifdef VMS |
120 | if (__gnat_ctrl_c_handler) | |
121 | __gnat_ctrl_c_handler = 0; | |
122 | #endif | |
70482933 | 123 | } |
fbf5a39b AC |
124 | |
125 | /* Windows implementation */ | |
126 | ||
127 | #elif defined (__MINGW32__) | |
128 | ||
129 | #include "mingw32.h" | |
130 | #include <windows.h> | |
131 | ||
25412599 | 132 | void (*sigint_intercepted) (void) = NULL; |
fbf5a39b AC |
133 | |
134 | static BOOL WINAPI | |
135 | __gnat_int_handler (DWORD dwCtrlType) | |
136 | { | |
137 | switch (dwCtrlType) | |
138 | { | |
139 | case CTRL_C_EVENT: | |
140 | case CTRL_BREAK_EVENT: | |
141 | if (sigint_intercepted != 0) | |
2fe53bf5 EB |
142 | { |
143 | sigint_intercepted (); | |
144 | return TRUE; | |
145 | } | |
fbf5a39b AC |
146 | break; |
147 | ||
148 | case CTRL_CLOSE_EVENT: | |
149 | case CTRL_LOGOFF_EVENT: | |
150 | case CTRL_SHUTDOWN_EVENT: | |
151 | break; | |
152 | } | |
2fe53bf5 EB |
153 | |
154 | return FALSE; | |
fbf5a39b AC |
155 | } |
156 | ||
157 | void | |
158 | __gnat_install_int_handler (void (*proc) (void)) | |
159 | { | |
160 | if (sigint_intercepted == NULL) | |
161 | SetConsoleCtrlHandler (__gnat_int_handler, TRUE); | |
162 | ||
163 | sigint_intercepted = proc; | |
164 | } | |
165 | ||
166 | void | |
9373164a | 167 | __gnat_uninstall_int_handler (void) |
fbf5a39b AC |
168 | { |
169 | if (sigint_intercepted != NULL) | |
170 | SetConsoleCtrlHandler (__gnat_int_handler, FALSE); | |
171 | ||
172 | sigint_intercepted = NULL; | |
173 | } | |
174 | ||
175 | /* Default implementation: do nothing */ | |
176 | ||
177 | #else | |
178 | ||
179 | void | |
180 | __gnat_install_int_handler (void (*proc) (void) __attribute__ ((unused))) | |
181 | { | |
182 | } | |
183 | ||
184 | void | |
9373164a | 185 | __gnat_uninstall_int_handler (void) |
fbf5a39b AC |
186 | { |
187 | } | |
188 | #endif |