]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/ntp/libntp/syssignal.c
MFC r338126: MFV r338092: ntp 4.2.8p12.
[FreeBSD/stable/10.git] / contrib / ntp / libntp / syssignal.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdio.h>
6 #include <sys/types.h>
7 #include <signal.h>
8
9 #include "ntp_syslog.h"
10 #include "ntp_stdlib.h"
11
12 static ctrl_c_fn        ctrl_c_hook;
13 #ifndef SYS_WINNT
14 RETSIGTYPE sigint_handler(int);
15 #else
16 BOOL WINAPI console_event_handler(DWORD);
17 #endif
18
19
20 #ifdef HAVE_SIGACTION
21
22 # ifdef SA_RESTART
23 #  define Z_SA_RESTART          SA_RESTART
24 # else
25 #  define Z_SA_RESTART          0
26 # endif
27
28 void
29 signal_no_reset(
30         int sig,
31         void (*func)(int)
32         )
33 {
34         int n;
35         struct sigaction vec;
36         struct sigaction ovec;
37
38         ZERO(vec);
39         sigemptyset(&vec.sa_mask);
40         vec.sa_handler = func;
41
42         /* Added for PPS clocks on Solaris 7 which get EINTR errors */
43 # ifdef SIGPOLL
44         if (SIGPOLL == sig)
45                 vec.sa_flags = Z_SA_RESTART;
46 # endif
47 # ifdef SIGIO
48         if (SIGIO == sig)
49                 vec.sa_flags = Z_SA_RESTART;
50 # endif
51
52         do
53                 n = sigaction(sig, &vec, &ovec);
54         while (-1 == n && EINTR == errno);
55         if (-1 == n) {
56                 perror("sigaction");
57                 exit(1);
58         }
59 }
60
61 #elif  HAVE_SIGVEC
62
63 void
64 signal_no_reset(
65         int sig,
66         RETSIGTYPE (*func)(int)
67         )
68 {
69         struct sigvec sv;
70         int n;
71
72         ZERO(sv);
73         sv.sv_handler = func;
74         n = sigvec(sig, &sv, (struct sigvec *)NULL);
75         if (-1 == n) {
76                 perror("sigvec");
77                 exit(1);
78         }
79 }
80
81 #elif  HAVE_SIGSET
82
83 void
84 signal_no_reset(
85         int sig,
86         RETSIGTYPE (*func)(int)
87         )
88 {
89         int n;
90
91         n = sigset(sig, func);
92         if (-1 == n) {
93                 perror("sigset");
94                 exit(1);
95         }
96 }
97
98 #else
99
100 /* Beware!      This implementation resets the signal to SIG_DFL */
101 void
102 signal_no_reset(
103         int sig,
104         RETSIGTYPE (*func)(int)
105         )
106 {
107 #ifndef SIG_ERR
108 # define SIG_ERR        (-1)
109 #endif
110         if (SIG_ERR == signal(sig, func)) {
111                 perror("signal");
112                 exit(1);
113         }
114 }
115
116 #endif
117
118 #ifndef SYS_WINNT
119 /*
120  * POSIX implementation of set_ctrl_c_hook()
121  */
122 RETSIGTYPE
123 sigint_handler(
124         int     signum
125         )
126 {
127         UNUSED_ARG(signum);
128         if (ctrl_c_hook != NULL)
129                 (*ctrl_c_hook)();
130 }
131
132 void
133 set_ctrl_c_hook(
134         ctrl_c_fn       c_hook
135         )
136 {
137         RETSIGTYPE (*handler)(int);
138
139         if (NULL == c_hook) {
140                 handler = SIG_DFL;
141                 signal_no_reset(SIGINT, handler);
142                 ctrl_c_hook = c_hook;
143         } else {
144                 ctrl_c_hook = c_hook;
145                 handler = &sigint_handler;
146                 signal_no_reset(SIGINT, handler);
147         }
148 }
149 #else   /* SYS_WINNT follows */
150 /*
151  * Windows implementation of set_ctrl_c_hook()
152  */
153 BOOL WINAPI 
154 console_event_handler(  
155         DWORD   dwCtrlType
156         )
157 {
158         BOOL handled;
159
160         if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) {
161                 (*ctrl_c_hook)();
162                 handled = TRUE;
163         } else {
164                 handled = FALSE;
165         }
166
167         return handled;
168 }
169 void
170 set_ctrl_c_hook(
171         ctrl_c_fn       c_hook
172         )
173 {
174         BOOL install;
175
176         if (NULL == c_hook) {
177                 ctrl_c_hook = NULL;
178                 install = FALSE;
179         } else {
180                 ctrl_c_hook = c_hook;
181                 install = TRUE;
182         }
183         if (!SetConsoleCtrlHandler(&console_event_handler, install))
184                 msyslog(LOG_ERR, "Can't %s console control handler: %m",
185                         (install)
186                             ? "add"
187                             : "remove");
188 }
189 #endif  /* SYS_WINNT */