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