/*++
/* NAME
/*	bounce_cleanup 3
/* SUMMARY
/*	cleanup logfile upon error
/* SYNOPSIS
/*	#include "bounce_service.h"
/*
/*	int	bounce_cleanup_registered()
/*
/*	void	bounce_cleanup_register(queue_id)
/*	char	*queue_id;
/*
/*	void	bounce_cleanup_log(void)
/*
/*	void	bounce_cleanup_unregister(void)
/* DESCRIPTION
/*	This module implements support for deleting the current
/*	bounce logfile in case of errors, and upon the arrival
/*	of a SIGTERM signal (shutdown).
/*
/*	bounce_cleanup_register() registers a callback routine with the
/*	run-time error handler, for automatic logfile removal in case
/*	of a fatal run-time error.
/*
/*	bounce_cleanup_unregister() cleans up storage used by
/*	bounce_cleanup_register().
/*
/*	In-between bounce_cleanup_register() and bounce_cleanup_unregister()
/*	calls, a call of bounce_cleanup_log() will delete the registered
/*	bounce logfile.
/*
/*	bounce_cleanup_registered() returns non-zero when a cleanup
/*	trap has been set.
/* DIAGNOSTICS
/*	Fatal error: all file access errors. Panic: nested calls of
/*	bounce_cleanup_register(); any calls of bounce_cleanup_unregister()
/*	or bounce_cleanup_log() without preceding bounce_cleanup_register()
/*	call.
/* BUGS
/* SEE ALSO
/*	master(8) process manager
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <vstring.h>

/* Global library. */

#include <mail_queue.h>

/* Application-specific. */

#include "bounce_service.h"

 /*
  * Support for removing a logfile when an update fails. In order to do this,
  * we save a copy of the currently-open logfile name, and register a
  * callback function pointer with the run-time error handler. The saved
  * pathname is made global so that the application can see whether or not a
  * trap was set up.
  */
static MSG_CLEANUP_FN bounce_cleanup_func;	/* saved callback */
VSTRING *bounce_cleanup_path;		/* saved path name */

/* bounce_cleanup_callback - run-time callback to cleanup logfile */

static void bounce_cleanup_callback(void)
{

    /*
     * Remove the logfile.
     */
    if (bounce_cleanup_path)
	bounce_cleanup_log();

    /*
     * Execute the saved cleanup action.
     */
    if (bounce_cleanup_func)
	bounce_cleanup_func();
}

/* bounce_cleanup_log - clean up the logfile */

void    bounce_cleanup_log(void)
{
    const char *myname = "bounce_cleanup_log";

    /*
     * Sanity checks.
     */
    if (bounce_cleanup_path == 0)
	msg_panic("%s: no cleanup context", myname);

    /*
     * This function may be called before a logfile is created or after it
     * has been deleted, so do not complain.
     */
    (void) unlink(vstring_str(bounce_cleanup_path));
}

/* bounce_cleanup_sig - signal handler */

static void bounce_cleanup_sig(int sig)
{

    /*
     * Running as a signal handler - don't do complicated stuff.
     */
    if (bounce_cleanup_path)
	(void) unlink(vstring_str(bounce_cleanup_path));
    _exit(sig);
}

/* bounce_cleanup_register - register logfile to clean up */

void    bounce_cleanup_register(char *service, char *queue_id)
{
    const char *myname = "bounce_cleanup_register";

    /*
     * Sanity checks.
     */
    if (bounce_cleanup_path)
	msg_panic("%s: nested call", myname);

    /*
     * Save a copy of the logfile path, and of the last callback function
     * pointer registered with the run-time error handler.
     */
    bounce_cleanup_path = vstring_alloc(10);
    (void) mail_queue_path(bounce_cleanup_path, service, queue_id);
    bounce_cleanup_func = msg_cleanup(bounce_cleanup_callback);
    signal(SIGTERM, bounce_cleanup_sig);
}

/* bounce_cleanup_unregister - unregister logfile to clean up */

void    bounce_cleanup_unregister(void)
{
    const char *myname = "bounce_cleanup_unregister";

    /*
     * Sanity checks.
     */
    if (bounce_cleanup_path == 0)
	msg_panic("%s: no cleanup context", myname);

    /*
     * Restore the saved callback function pointer, and release storage for
     * the saved logfile pathname.
     */
    signal(SIGTERM, SIG_DFL);
    (void) msg_cleanup(bounce_cleanup_func);
    vstring_free(bounce_cleanup_path);
    bounce_cleanup_path = 0;
}
