1 /*****************************************************************************
2
3 POPular -- A POP3 server and proxy for large mail systems
4
5 $Id: sig.c,v 1.6 2002/09/15 12:27:16 sqrt Exp $
6
7 http://www.remote.org/jochen/mail/popular/
8
9 ******************************************************************************
10
11 Copyright (C) 1999-2002 Jochen Topf <jochen@remote.org>
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
26
27 *****************************************************************************/
28
29 #if HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include "popular.h"
34 #include "sig.h"
35
36
37 static volatile int signal_remember[SIGNAL_MAX];
38
39
40 /*****************************************************************************
41
42 signal_handler()
43
44 The signal handler just saves the information which signal occurred into
45 an array.
46
47 *****************************************************************************/
48 void
signal_handler(int signum)49 signal_handler(int signum)
50 {
51 if (signum < SIGNAL_MAX) signal_remember[signum] = 1;
52 }
53
54
55 /*****************************************************************************
56
57 signal_set()
58
59 *****************************************************************************/
60 void
signal_set(signal_handler_t what,int signum,int flags)61 signal_set(signal_handler_t what, int signum, int flags)
62 {
63 struct sigaction sigAction;
64 memset(&sigAction, 0, sizeof(sigAction));
65 sigemptyset(&sigAction.sa_mask);
66
67 switch (what) {
68 case sigIgnore:
69 sigAction.sa_handler = SIG_IGN;
70 sigAction.sa_flags = 0;
71 break;
72 case sigDefault:
73 sigAction.sa_handler = SIG_DFL;
74 sigAction.sa_flags = 0;
75 break;
76 case sigHandler:
77 sigAction.sa_handler = signal_handler;
78 sigAction.sa_flags = SA_RESTART | flags;
79 break;
80 }
81
82 if (sigaction(signum, &sigAction, (struct sigaction *)0) != 0) {
83 /* XLOG-DOC:BUG:014a:sigaction_failed
84 * A sigaction () system call failed. This should never happen. */
85 xlog_printf(xlog_bug, 0x014a, "sigaction_failed signal=%d", signum);
86 }
87 }
88
89
90 /*****************************************************************************
91
92 signal_init(int c)
93
94 Setup standard signal handling for servers.
95
96 c=1: Call signal handler if child dies
97
98 *****************************************************************************/
99 void
signal_init(int c)100 signal_init(int c)
101 {
102 int i;
103 for (i=0; i < SIGNAL_MAX; i++) signal_remember[i] = 0;
104
105 signal_set(sigIgnore, SIGPIPE, 0);
106 if (c) {
107 signal_set(sigHandler, SIGCHLD, SA_NOCLDSTOP);
108 } else {
109 signal_set(sigDefault, SIGCHLD, 0);
110 }
111 signal_set(sigHandler, SIGHUP, 0);
112 signal_set(sigHandler, SIGTERM, 0);
113 signal_set(sigHandler, SIGINT, 0);
114 signal_set(sigHandler, SIGQUIT, 0);
115 signal_set(sigHandler, SIGUSR1, 0);
116 signal_set(sigHandler, SIGUSR2, 0);
117 }
118
119
120 /*****************************************************************************
121
122 signal_init_child()
123
124 Setup standard signal handling for children of servers.
125
126 *****************************************************************************/
127 void
signal_init_child()128 signal_init_child()
129 {
130 int i;
131
132 signal_set(sigIgnore, SIGPIPE, 0);
133 signal_set(sigDefault, SIGCHLD, 0);
134 signal_set(sigDefault, SIGHUP, 0);
135 signal_set(sigDefault, SIGTERM, 0);
136 signal_set(sigDefault, SIGINT, 0);
137 signal_set(sigDefault, SIGQUIT, 0);
138 signal_set(sigDefault, SIGUSR1, 0);
139 signal_set(sigDefault, SIGUSR2, 0);
140
141 if (signal_remember[SIGTERM] || signal_remember[SIGINT]) {
142 /* XLOG-DOC:INF:0133:got_term_signal
143 * The child got a TERM or INT signal and will shut down. This signal
144 * was either delivered to the parent between the last check for signals
145 * and the fork, or it was delivered to the child before the child
146 * could change its signal handling to the default behaviour. In any
147 * case, calling exit immediately is the right thing to do here. */
148 xlog_printf(xlog_inf, 0x0133, "got_term_signal");
149 exit(0);
150 }
151 for (i=0; i < SIGNAL_MAX; i++) signal_remember[i] = 0;
152 }
153
154
155 /*****************************************************************************
156
157 signal_came()
158
159 Return 1 if the specified signal arrived, 0 otherwise.
160
161 *****************************************************************************/
162 int
signal_came(int signum)163 signal_came(int signum)
164 {
165 if (signum < SIGNAL_MAX) {
166 int ret = signal_remember[signum];
167 signal_remember[signum] = 0;
168 return ret;
169 }
170 return 0;
171 }
172
173
174 /*****************************************************************************
175
176 signal_next()
177
178 Return the next signal, that was caught. If there was no signal, return 0.
179
180 *****************************************************************************/
181 int
signal_next()182 signal_next()
183 {
184 int n;
185
186 for (n=1; n < SIGNAL_MAX; n++) {
187 if (signal_remember[n]) {
188 signal_remember[n] = 0;
189 return n;
190 }
191 }
192
193 return 0;
194 }
195
196
197 /** THE END *****************************************************************/
198