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