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