1/*++
2/* NAME
3/*	bounce_cleanup 3
4/* SUMMARY
5/*	cleanup logfile upon error
6/* SYNOPSIS
7/*	#include "bounce_service.h"
8/*
9/*	int	bounce_cleanup_registered()
10/*
11/*	void	bounce_cleanup_register(queue_id)
12/*	char	*queue_id;
13/*
14/*	void	bounce_cleanup_log(void)
15/*
16/*	void	bounce_cleanup_unregister(void)
17/* DESCRIPTION
18/*	This module implements support for deleting the current
19/*	bounce logfile in case of errors, and upon the arrival
20/*	of a SIGTERM signal (shutdown).
21/*
22/*	bounce_cleanup_register() registers a callback routine with the
23/*	run-time error handler, for automatic logfile removal in case
24/*	of a fatal run-time error.
25/*
26/*	bounce_cleanup_unregister() cleans up storage used by
27/*	bounce_cleanup_register().
28/*
29/*	In-between bounce_cleanup_register() and bounce_cleanup_unregister()
30/*	calls, a call of bounce_cleanup_log() will delete the registered
31/*	bounce logfile.
32/*
33/*	bounce_cleanup_registered() returns non-zero when a cleanup
34/*	trap has been set.
35/* DIAGNOSTICS
36/*	Fatal error: all file access errors. Panic: nested calls of
37/*	bounce_cleanup_register(); any calls of bounce_cleanup_unregister()
38/*	or bounce_cleanup_log() without preceding bounce_cleanup_register()
39/*	call.
40/* BUGS
41/* SEE ALSO
42/*	master(8) process manager
43/* LICENSE
44/* .ad
45/* .fi
46/*	The Secure Mailer license must be distributed with this software.
47/* AUTHOR(S)
48/*	Wietse Venema
49/*	IBM T.J. Watson Research
50/*	P.O. Box 704
51/*	Yorktown Heights, NY 10598, USA
52/*--*/
53
54/* System library. */
55
56#include <sys_defs.h>
57#include <unistd.h>
58#include <signal.h>
59#include <stdlib.h>
60
61/* Utility library. */
62
63#include <msg.h>
64#include <mymalloc.h>
65#include <vstring.h>
66
67/* Global library. */
68
69#include <mail_queue.h>
70
71/* Application-specific. */
72
73#include "bounce_service.h"
74
75 /*
76  * Support for removing a logfile when an update fails. In order to do this,
77  * we save a copy of the currently-open logfile name, and register a
78  * callback function pointer with the run-time error handler. The saved
79  * pathname is made global so that the application can see whether or not a
80  * trap was set up.
81  */
82static MSG_CLEANUP_FN bounce_cleanup_func;	/* saved callback */
83VSTRING *bounce_cleanup_path;		/* saved path name */
84
85/* bounce_cleanup_callback - run-time callback to cleanup logfile */
86
87static void bounce_cleanup_callback(void)
88{
89
90    /*
91     * Remove the logfile.
92     */
93    if (bounce_cleanup_path)
94	bounce_cleanup_log();
95
96    /*
97     * Execute the saved cleanup action.
98     */
99    if (bounce_cleanup_func)
100	bounce_cleanup_func();
101}
102
103/* bounce_cleanup_log - clean up the logfile */
104
105void    bounce_cleanup_log(void)
106{
107    const char *myname = "bounce_cleanup_log";
108
109    /*
110     * Sanity checks.
111     */
112    if (bounce_cleanup_path == 0)
113	msg_panic("%s: no cleanup context", myname);
114
115    /*
116     * This function may be called before a logfile is created or after it
117     * has been deleted, so do not complain.
118     */
119    (void) unlink(vstring_str(bounce_cleanup_path));
120}
121
122/* bounce_cleanup_sig - signal handler */
123
124static void bounce_cleanup_sig(int sig)
125{
126
127    /*
128     * Running as a signal handler - don't do complicated stuff.
129     */
130    if (bounce_cleanup_path)
131	(void) unlink(vstring_str(bounce_cleanup_path));
132    _exit(sig);
133}
134
135/* bounce_cleanup_register - register logfile to clean up */
136
137void    bounce_cleanup_register(char *service, char *queue_id)
138{
139    const char *myname = "bounce_cleanup_register";
140
141    /*
142     * Sanity checks.
143     */
144    if (bounce_cleanup_path)
145	msg_panic("%s: nested call", myname);
146
147    /*
148     * Save a copy of the logfile path, and of the last callback function
149     * pointer registered with the run-time error handler.
150     */
151    bounce_cleanup_path = vstring_alloc(10);
152    (void) mail_queue_path(bounce_cleanup_path, service, queue_id);
153    bounce_cleanup_func = msg_cleanup(bounce_cleanup_callback);
154    signal(SIGTERM, bounce_cleanup_sig);
155}
156
157/* bounce_cleanup_unregister - unregister logfile to clean up */
158
159void    bounce_cleanup_unregister(void)
160{
161    const char *myname = "bounce_cleanup_unregister";
162
163    /*
164     * Sanity checks.
165     */
166    if (bounce_cleanup_path == 0)
167	msg_panic("%s: no cleanup context", myname);
168
169    /*
170     * Restore the saved callback function pointer, and release storage for
171     * the saved logfile pathname.
172     */
173    signal(SIGTERM, SIG_DFL);
174    (void) msg_cleanup(bounce_cleanup_func);
175    vstring_free(bounce_cleanup_path);
176    bounce_cleanup_path = 0;
177}
178