106f25ae9SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 1999-2004, 2006 Proofpoint, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro * All rights reserved.
406f25ae9SGregory Neil Shapiro *
506f25ae9SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
606f25ae9SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
706f25ae9SGregory Neil Shapiro * the sendmail distribution.
806f25ae9SGregory Neil Shapiro *
906f25ae9SGregory Neil Shapiro */
1006f25ae9SGregory Neil Shapiro
1140266059SGregory Neil Shapiro #include <sm/gen.h>
124313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: signal.c,v 8.45 2013-11-22 20:51:36 ca Exp $")
1306f25ae9SGregory Neil Shapiro
1406f25ae9SGregory Neil Shapiro #include "libmilter.h"
1506f25ae9SGregory Neil Shapiro
1606f25ae9SGregory Neil Shapiro /*
1706f25ae9SGregory Neil Shapiro ** thread to handle signals
1806f25ae9SGregory Neil Shapiro */
1906f25ae9SGregory Neil Shapiro
2006f25ae9SGregory Neil Shapiro static smutex_t M_Mutex;
2106f25ae9SGregory Neil Shapiro
2206f25ae9SGregory Neil Shapiro static int MilterStop = MILTER_CONT;
2306f25ae9SGregory Neil Shapiro
24b6bacd31SGregory Neil Shapiro static void *mi_signal_thread __P((void *));
25b6bacd31SGregory Neil Shapiro static int mi_spawn_signal_thread __P((char *));
26b6bacd31SGregory Neil Shapiro
2740266059SGregory Neil Shapiro /*
2806f25ae9SGregory Neil Shapiro ** MI_STOP -- return value of MilterStop
2906f25ae9SGregory Neil Shapiro **
3006f25ae9SGregory Neil Shapiro ** Parameters:
3106f25ae9SGregory Neil Shapiro ** none.
3206f25ae9SGregory Neil Shapiro **
3306f25ae9SGregory Neil Shapiro ** Returns:
3406f25ae9SGregory Neil Shapiro ** value of MilterStop
3506f25ae9SGregory Neil Shapiro */
3606f25ae9SGregory Neil Shapiro
3706f25ae9SGregory Neil Shapiro int
mi_stop()3806f25ae9SGregory Neil Shapiro mi_stop()
3906f25ae9SGregory Neil Shapiro {
4006f25ae9SGregory Neil Shapiro return MilterStop;
4106f25ae9SGregory Neil Shapiro }
4240266059SGregory Neil Shapiro /*
4306f25ae9SGregory Neil Shapiro ** MI_STOP_MILTERS -- set value of MilterStop
4406f25ae9SGregory Neil Shapiro **
4506f25ae9SGregory Neil Shapiro ** Parameters:
4606f25ae9SGregory Neil Shapiro ** v -- new value for MilterStop.
4706f25ae9SGregory Neil Shapiro **
4806f25ae9SGregory Neil Shapiro ** Returns:
4906f25ae9SGregory Neil Shapiro ** none.
5006f25ae9SGregory Neil Shapiro */
5106f25ae9SGregory Neil Shapiro
5206f25ae9SGregory Neil Shapiro void
mi_stop_milters(v)5306f25ae9SGregory Neil Shapiro mi_stop_milters(v)
5406f25ae9SGregory Neil Shapiro int v;
5506f25ae9SGregory Neil Shapiro {
5606f25ae9SGregory Neil Shapiro (void) smutex_lock(&M_Mutex);
5706f25ae9SGregory Neil Shapiro if (MilterStop < v)
5806f25ae9SGregory Neil Shapiro MilterStop = v;
5942e5d165SGregory Neil Shapiro
6042e5d165SGregory Neil Shapiro /* close listen socket */
6142e5d165SGregory Neil Shapiro mi_closener();
6206f25ae9SGregory Neil Shapiro (void) smutex_unlock(&M_Mutex);
6306f25ae9SGregory Neil Shapiro }
6440266059SGregory Neil Shapiro /*
6506f25ae9SGregory Neil Shapiro ** MI_CLEAN_SIGNALS -- clean up signal handler thread
6606f25ae9SGregory Neil Shapiro **
6706f25ae9SGregory Neil Shapiro ** Parameters:
6806f25ae9SGregory Neil Shapiro ** none.
6906f25ae9SGregory Neil Shapiro **
7006f25ae9SGregory Neil Shapiro ** Returns:
7106f25ae9SGregory Neil Shapiro ** none.
7206f25ae9SGregory Neil Shapiro */
7306f25ae9SGregory Neil Shapiro
7406f25ae9SGregory Neil Shapiro void
mi_clean_signals()7506f25ae9SGregory Neil Shapiro mi_clean_signals()
7606f25ae9SGregory Neil Shapiro {
7706f25ae9SGregory Neil Shapiro (void) smutex_destroy(&M_Mutex);
7806f25ae9SGregory Neil Shapiro }
7940266059SGregory Neil Shapiro /*
8006f25ae9SGregory Neil Shapiro ** MI_SIGNAL_THREAD -- thread to deal with signals
8106f25ae9SGregory Neil Shapiro **
8206f25ae9SGregory Neil Shapiro ** Parameters:
8306f25ae9SGregory Neil Shapiro ** name -- name of milter
8406f25ae9SGregory Neil Shapiro **
8506f25ae9SGregory Neil Shapiro ** Returns:
8606f25ae9SGregory Neil Shapiro ** NULL
8706f25ae9SGregory Neil Shapiro */
8806f25ae9SGregory Neil Shapiro
8906f25ae9SGregory Neil Shapiro static void *
mi_signal_thread(name)9006f25ae9SGregory Neil Shapiro mi_signal_thread(name)
9106f25ae9SGregory Neil Shapiro void *name;
9206f25ae9SGregory Neil Shapiro {
934e4196cbSGregory Neil Shapiro int sig, errs, sigerr;
9406f25ae9SGregory Neil Shapiro sigset_t set;
9506f25ae9SGregory Neil Shapiro
96a7ec597cSGregory Neil Shapiro (void) sigemptyset(&set);
97a7ec597cSGregory Neil Shapiro (void) sigaddset(&set, SIGHUP);
98a7ec597cSGregory Neil Shapiro (void) sigaddset(&set, SIGTERM);
9906f25ae9SGregory Neil Shapiro
10006f25ae9SGregory Neil Shapiro /* Handle Ctrl-C gracefully for debugging */
101a7ec597cSGregory Neil Shapiro (void) sigaddset(&set, SIGINT);
10206f25ae9SGregory Neil Shapiro errs = 0;
10306f25ae9SGregory Neil Shapiro
104a7ec597cSGregory Neil Shapiro for (;;)
10506f25ae9SGregory Neil Shapiro {
1064e4196cbSGregory Neil Shapiro sigerr = sig = 0;
107*da7d7b9cSGregory Neil Shapiro #if SIGWAIT_TAKES_1_ARG
10806f25ae9SGregory Neil Shapiro if ((sig = sigwait(&set)) < 0)
109*da7d7b9cSGregory Neil Shapiro #else
1104e4196cbSGregory Neil Shapiro if ((sigerr = sigwait(&set, &sig)) != 0)
111*da7d7b9cSGregory Neil Shapiro #endif
11206f25ae9SGregory Neil Shapiro {
1134e4196cbSGregory Neil Shapiro /* some OS return -1 and set errno: copy it */
1144e4196cbSGregory Neil Shapiro if (sigerr <= 0)
1154e4196cbSGregory Neil Shapiro sigerr = errno;
1164e4196cbSGregory Neil Shapiro
11713bd1963SGregory Neil Shapiro /* this can happen on OSF/1 (at least) */
1184e4196cbSGregory Neil Shapiro if (sigerr == EINTR)
11913bd1963SGregory Neil Shapiro continue;
12006f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR,
12140266059SGregory Neil Shapiro "%s: sigwait returned error: %d",
1224e4196cbSGregory Neil Shapiro (char *)name, sigerr);
12306f25ae9SGregory Neil Shapiro if (++errs > MAX_FAILS_T)
12406f25ae9SGregory Neil Shapiro {
12506f25ae9SGregory Neil Shapiro mi_stop_milters(MILTER_ABRT);
12606f25ae9SGregory Neil Shapiro return NULL;
12706f25ae9SGregory Neil Shapiro }
12806f25ae9SGregory Neil Shapiro continue;
12906f25ae9SGregory Neil Shapiro }
13006f25ae9SGregory Neil Shapiro errs = 0;
13106f25ae9SGregory Neil Shapiro
13206f25ae9SGregory Neil Shapiro switch (sig)
13306f25ae9SGregory Neil Shapiro {
13406f25ae9SGregory Neil Shapiro case SIGHUP:
13506f25ae9SGregory Neil Shapiro case SIGTERM:
13606f25ae9SGregory Neil Shapiro mi_stop_milters(MILTER_STOP);
13706f25ae9SGregory Neil Shapiro return NULL;
13806f25ae9SGregory Neil Shapiro case SIGINT:
13906f25ae9SGregory Neil Shapiro mi_stop_milters(MILTER_ABRT);
14006f25ae9SGregory Neil Shapiro return NULL;
14106f25ae9SGregory Neil Shapiro default:
14206f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR,
14306f25ae9SGregory Neil Shapiro "%s: sigwait returned unmasked signal: %d",
14406f25ae9SGregory Neil Shapiro (char *)name, sig);
14506f25ae9SGregory Neil Shapiro break;
14606f25ae9SGregory Neil Shapiro }
14706f25ae9SGregory Neil Shapiro }
148a7ec597cSGregory Neil Shapiro /* NOTREACHED */
14906f25ae9SGregory Neil Shapiro }
15040266059SGregory Neil Shapiro /*
15106f25ae9SGregory Neil Shapiro ** MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals
15206f25ae9SGregory Neil Shapiro **
15306f25ae9SGregory Neil Shapiro ** Parameters:
15406f25ae9SGregory Neil Shapiro ** name -- name of milter
15506f25ae9SGregory Neil Shapiro **
15606f25ae9SGregory Neil Shapiro ** Returns:
15706f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
15806f25ae9SGregory Neil Shapiro */
15906f25ae9SGregory Neil Shapiro
16006f25ae9SGregory Neil Shapiro static int
mi_spawn_signal_thread(name)16106f25ae9SGregory Neil Shapiro mi_spawn_signal_thread(name)
16206f25ae9SGregory Neil Shapiro char *name;
16306f25ae9SGregory Neil Shapiro {
16406f25ae9SGregory Neil Shapiro sthread_t tid;
16540266059SGregory Neil Shapiro int r;
16606f25ae9SGregory Neil Shapiro sigset_t set;
16706f25ae9SGregory Neil Shapiro
16806f25ae9SGregory Neil Shapiro /* Mask HUP and KILL signals */
169a7ec597cSGregory Neil Shapiro (void) sigemptyset(&set);
170a7ec597cSGregory Neil Shapiro (void) sigaddset(&set, SIGHUP);
171a7ec597cSGregory Neil Shapiro (void) sigaddset(&set, SIGTERM);
172a7ec597cSGregory Neil Shapiro (void) sigaddset(&set, SIGINT);
17306f25ae9SGregory Neil Shapiro
17406f25ae9SGregory Neil Shapiro if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0)
17506f25ae9SGregory Neil Shapiro {
17606f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR,
17706f25ae9SGregory Neil Shapiro "%s: Couldn't mask HUP and KILL signals", name);
17806f25ae9SGregory Neil Shapiro return MI_FAILURE;
17906f25ae9SGregory Neil Shapiro }
18040266059SGregory Neil Shapiro r = thread_create(&tid, mi_signal_thread, (void *)name);
18140266059SGregory Neil Shapiro if (r != 0)
18206f25ae9SGregory Neil Shapiro {
18306f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR,
18440266059SGregory Neil Shapiro "%s: Couldn't start signal thread: %d",
18540266059SGregory Neil Shapiro name, r);
18606f25ae9SGregory Neil Shapiro return MI_FAILURE;
18706f25ae9SGregory Neil Shapiro }
18806f25ae9SGregory Neil Shapiro return MI_SUCCESS;
18906f25ae9SGregory Neil Shapiro }
19040266059SGregory Neil Shapiro /*
19106f25ae9SGregory Neil Shapiro ** MI_CONTROL_STARTUP -- startup for thread to handle signals
19206f25ae9SGregory Neil Shapiro **
19306f25ae9SGregory Neil Shapiro ** Parameters:
19406f25ae9SGregory Neil Shapiro ** name -- name of milter
19506f25ae9SGregory Neil Shapiro **
19606f25ae9SGregory Neil Shapiro ** Returns:
19706f25ae9SGregory Neil Shapiro ** MI_SUCCESS/MI_FAILURE
19806f25ae9SGregory Neil Shapiro */
19906f25ae9SGregory Neil Shapiro
20006f25ae9SGregory Neil Shapiro int
mi_control_startup(name)20106f25ae9SGregory Neil Shapiro mi_control_startup(name)
20206f25ae9SGregory Neil Shapiro char *name;
20306f25ae9SGregory Neil Shapiro {
20406f25ae9SGregory Neil Shapiro
20506f25ae9SGregory Neil Shapiro if (!smutex_init(&M_Mutex))
20606f25ae9SGregory Neil Shapiro {
20706f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR,
20806f25ae9SGregory Neil Shapiro "%s: Couldn't initialize control pipe mutex", name);
20906f25ae9SGregory Neil Shapiro return MI_FAILURE;
21006f25ae9SGregory Neil Shapiro }
21106f25ae9SGregory Neil Shapiro
21206f25ae9SGregory Neil Shapiro /*
21306f25ae9SGregory Neil Shapiro ** spawn_signal_thread must happen before other threads are spawned
21406f25ae9SGregory Neil Shapiro ** off so that it can mask the right signals and other threads
21506f25ae9SGregory Neil Shapiro ** will inherit that mask.
21606f25ae9SGregory Neil Shapiro */
21706f25ae9SGregory Neil Shapiro if (mi_spawn_signal_thread(name) == MI_FAILURE)
21806f25ae9SGregory Neil Shapiro {
21906f25ae9SGregory Neil Shapiro smi_log(SMI_LOG_ERR,
22006f25ae9SGregory Neil Shapiro "%s: Couldn't spawn signal thread", name);
22106f25ae9SGregory Neil Shapiro (void) smutex_destroy(&M_Mutex);
22206f25ae9SGregory Neil Shapiro return MI_FAILURE;
22306f25ae9SGregory Neil Shapiro }
22406f25ae9SGregory Neil Shapiro return MI_SUCCESS;
22506f25ae9SGregory Neil Shapiro }
226