]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/libntp/syssignal.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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                 ctrl_c_hook = NULL;
142         } else {
143                 handler = &sigint_handler;
144                 ctrl_c_hook = c_hook;
145         }
146         signal_no_reset(SIGINT, handler);
147 }
148 #else   /* SYS_WINNT follows */
149 /*
150  * Windows implementation of set_ctrl_c_hook()
151  */
152 BOOL WINAPI 
153 console_event_handler(  
154         DWORD   dwCtrlType
155         )
156 {
157         BOOL handled;
158
159         if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) {
160                 (*ctrl_c_hook)();
161                 handled = TRUE;
162         } else {
163                 handled = FALSE;
164         }
165
166         return handled;
167 }
168 void
169 set_ctrl_c_hook(
170         ctrl_c_fn       c_hook
171         )
172 {
173         BOOL install;
174
175         if (NULL == c_hook) {
176                 ctrl_c_hook = NULL;
177                 install = FALSE;
178         } else {
179                 ctrl_c_hook = c_hook;
180                 install = TRUE;
181         }
182         if (!SetConsoleCtrlHandler(&console_event_handler, install))
183                 msyslog(LOG_ERR, "Can't %s console control handler: %m",
184                         (install)
185                             ? "add"
186                             : "remove");
187 }
188 #endif  /* SYS_WINNT */