1 /*
2 ** Copyright 1998 - 2006 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5 
6 #include	"maildrop.h"
7 #include	"exittrap.h"
8 #include	<signal.h>
9 #include	<sysexits.h>
10 #include	<errno.h>
11 #if SYSLOG_LOGGING
12 #include	<syslog.h>
13 #endif
14 
15 extern void killprocgroup();
16 
17 static const char rcsid[]="$Id: maildrop.C,v 1.7 2006/05/28 15:29:52 mrsam Exp $";
18 
19 int Maildrop::sigfpe;
20 
sig_fpe(int)21 static RETSIGTYPE sig_fpe(int)
22 {
23 	maildrop.sigfpe=1;
24 	signal (SIGFPE, sig_fpe);
25 #if RETSIGTYPE != void
26 	return (0);
27 #endif
28 }
29 
cleanup()30 void Maildrop::cleanup()
31 {
32 	ExitTrap::onexit();
33 	killprocgroup();
34 }
35 
bye(int n)36 RETSIGTYPE Maildrop::bye(int n)
37 {
38 static const char msg[]="maildrop: signal 0x";
39 static const char hex[]="0123456789ABCDEF";
40 
41 	cleanup();
42 	if (write(2, msg, sizeof(msg)-1) < 0 ||
43 	    write(2, hex+ ((n / 16) & 0x0F), 1) < 0 ||
44 	    write(2, hex+ (n & 0x0F), 1) < 0 ||
45 	    write(2, "\n", 1) < 0)
46 		; /* gcc shut up */
47 
48 	_exit(EX_TEMPFAIL);
49 
50 #if RETSIGTYPE != void
51 	return (0);
52 #endif
53 }
54 
trap(int (* func)(int,char * []),int argc,char * argv[])55 int Maildrop::trap(int (*func)(int, char *[]), int argc, char *argv[])
56 {
57 int	n;
58 
59 	for (n=0; n<NSIG; n++)
60 		signal(n, bye);
61 	signal(SIGPIPE, SIG_IGN);
62 #ifdef SIGWINCH
63 	signal(SIGWINCH, SIG_IGN);
64 #endif
65 	signal(SIGCHLD, SIG_DFL);
66 	signal(SIGFPE,  sig_fpe);
67 
68 #if SYSLOG_LOGGING
69 	openlog("maildrop", LOG_PID, LOG_MAIL);
70 #endif
71 
72 	try
73 	{
74 	int	r=(*func)(argc, argv);
75 
76 		cleanup();
77 		return (r);
78 	}
79 	catch (const char *p)
80 	{
81 		merr << argv[0] << ": " << p << "\n";
82 #if SYSLOG_LOGGING
83 		syslog(LOG_INFO, p);
84 #endif
85 		cleanup();
86 		return (EX_TEMPFAIL);
87 	}
88 #if NEED_NONCONST_EXCEPTIONS
89 	catch (char *p)
90 	{
91 		merr << argv[0] << ": " << p << "\n";
92 #if SYSLOG_LOGGING
93 		syslog(LOG_INFO, p);
94 #endif
95 		cleanup();
96 		return (EX_TEMPFAIL);
97 	}
98 #endif
99 	catch (int n)
100 	{
101 		cleanup();
102 		return (n);
103 	}
104 	catch (...)
105 	{
106 		merr << argv[0] << ": Internal error.\n";
107 #if SYSLOG_LOGGING
108 		syslog(LOG_INFO, "Internal error.");
109 #endif
110 		cleanup();
111 		return (EX_TEMPFAIL);
112 	}
113 }
114