]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/libmilter/signal.c
Import of sendmail version 8.11.1 into vendor branch SENDMAIL with
[FreeBSD/FreeBSD.git] / contrib / sendmail / libmilter / signal.c
1 /*
2  *  Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers.
3  *      All rights reserved.
4  *
5  * By using this file, you agree to the terms and conditions set
6  * forth in the LICENSE file which can be found at the top level of
7  * the sendmail distribution.
8  *
9  */
10
11 #ifndef lint
12 static char id[] = "@(#)$Id: signal.c,v 8.10.4.7 2000/09/01 00:49:04 ca Exp $";
13 #endif /* ! lint */
14
15 #if _FFR_MILTER
16 #include "libmilter.h"
17
18 typedef pthread_mutex_t smutex_t;
19 # define smutex_init(mp)        (pthread_mutex_init(mp, NULL) == 0)
20 # define smutex_destroy(mp)     (pthread_mutex_destroy(mp) == 0)
21 # define smutex_lock(mp)        (pthread_mutex_lock(mp) == 0)
22 # define smutex_unlock(mp)      (pthread_mutex_unlock(mp) == 0)
23 # define smutex_trylock(mp)     (pthread_mutex_trylock(mp) == 0)
24
25 /*
26 **  thread to handle signals
27 */
28
29 static smutex_t M_Mutex;
30
31 static int MilterStop = MILTER_CONT;
32
33 \f/*
34 **  MI_STOP -- return value of MilterStop
35 **
36 **      Parameters:
37 **              none.
38 **
39 **      Returns:
40 **              value of MilterStop
41 */
42
43 int
44 mi_stop()
45 {
46         return MilterStop;
47 }
48 \f/*
49 **  MI_STOP_MILTERS -- set value of MilterStop
50 **
51 **      Parameters:
52 **              v -- new value for MilterStop.
53 **
54 **      Returns:
55 **              none.
56 */
57
58 void
59 mi_stop_milters(v)
60         int v;
61 {
62         (void) smutex_lock(&M_Mutex);
63         if (MilterStop < v)
64                 MilterStop = v;
65
66         /* close listen socket */
67         mi_closener();
68         (void) smutex_unlock(&M_Mutex);
69 }
70 \f/*
71 **  MI_CLEAN_SIGNALS -- clean up signal handler thread
72 **
73 **      Parameters:
74 **              none.
75 **
76 **      Returns:
77 **              none.
78 */
79
80 void
81 mi_clean_signals()
82 {
83         (void) smutex_destroy(&M_Mutex);
84 }
85 \f/*
86 **  MI_SIGNAL_THREAD -- thread to deal with signals
87 **
88 **      Parameters:
89 **              name -- name of milter
90 **
91 **      Returns:
92 **              NULL
93 */
94
95 static void *
96 mi_signal_thread(name)
97         void *name;
98 {
99         int sig, errs;
100         sigset_t set;
101
102         sigemptyset(&set);
103         sigaddset(&set, SIGHUP);
104         sigaddset(&set, SIGTERM);
105
106         /* Handle Ctrl-C gracefully for debugging */
107         sigaddset(&set, SIGINT);
108         errs = 0;
109
110         while (TRUE)
111         {
112                 sig = 0;
113 #ifdef SOLARIS
114                 if ((sig = sigwait(&set)) < 0)
115 #else /* SOLARIS */
116                 if (sigwait(&set, &sig) != 0)
117 #endif /* SOLARIS */
118                 {
119                         smi_log(SMI_LOG_ERR,
120                                 "%s: sigwait returned error: %s",
121                                 (char *)name, strerror(errno));
122                         if (++errs > MAX_FAILS_T)
123                         {
124                                 mi_stop_milters(MILTER_ABRT);
125                                 return NULL;
126                         }
127                         continue;
128                 }
129                 errs = 0;
130
131                 switch (sig)
132                 {
133                   case SIGHUP:
134                   case SIGTERM:
135                         mi_stop_milters(MILTER_STOP);
136                         return NULL;
137                   case SIGINT:
138                         mi_stop_milters(MILTER_ABRT);
139                         return NULL;
140                   default:
141                         smi_log(SMI_LOG_ERR,
142                                 "%s: sigwait returned unmasked signal: %d",
143                                 (char *)name, sig);
144                         break;
145                 }
146         }
147 }
148 \f/*
149 **  MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals
150 **
151 **      Parameters:
152 **              name -- name of milter
153 **
154 **      Returns:
155 **              MI_SUCCESS/MI_FAILURE
156 */
157
158 static int
159 mi_spawn_signal_thread(name)
160         char *name;
161 {
162         sthread_t tid;
163         sigset_t set;
164
165         /* Mask HUP and KILL signals */
166         sigemptyset(&set);
167         sigaddset(&set, SIGHUP);
168         sigaddset(&set, SIGTERM);
169         sigaddset(&set, SIGINT);
170
171         if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0)
172         {
173                 smi_log(SMI_LOG_ERR,
174                         "%s: Couldn't mask HUP and KILL signals", name);
175                 return MI_FAILURE;
176         }
177         if (thread_create(&tid, mi_signal_thread,
178                           (void *)name) != MI_SUCCESS)
179         {
180                 smi_log(SMI_LOG_ERR,
181                         "%s: Couldn't start signal thread", name);
182                 return MI_FAILURE;
183         }
184         return MI_SUCCESS;
185 }
186 \f/*
187 **  MI_CONTROL_STARTUP -- startup for thread to handle signals
188 **
189 **      Parameters:
190 **              name -- name of milter
191 **
192 **      Returns:
193 **              MI_SUCCESS/MI_FAILURE
194 */
195
196 int
197 mi_control_startup(name)
198         char *name;
199 {
200
201         if (!smutex_init(&M_Mutex))
202         {
203                 smi_log(SMI_LOG_ERR,
204                         "%s: Couldn't initialize control pipe mutex", name);
205                 return MI_FAILURE;
206         }
207
208         /*
209         **  spawn_signal_thread must happen before other threads are spawned
210         **  off so that it can mask the right signals and other threads
211         **  will inherit that mask.
212         */
213         if (mi_spawn_signal_thread(name) == MI_FAILURE)
214         {
215                 smi_log(SMI_LOG_ERR,
216                         "%s: Couldn't spawn signal thread", name);
217                 (void) smutex_destroy(&M_Mutex);
218                 return MI_FAILURE;
219         }
220         return MI_SUCCESS;
221 }
222 #endif /* _FFR_MILTER */