/* cleanup - Hackercorp Hackercore, standard cleanup management routines, v1.2
  
   This code is released to the public domain, 5/9/88, by Peter da Silva
   and Karl Lehenbauer
  
   Usage:
  
  	add_cleanup(cleanup_routine);
  	void cleanup_routine();

  		Add a routine to the cleanup list.  When cleanup  is called, routines 
		passed as arguments to add_cleanup will be executed  in the reverse 
		order in which they were received.  See the source to  the IFF CAT 
		archiver, iffar, for an example of how to use this.

	void cleanup()

		Execute all the routines passed as arguments to add_cleanup
  	
	panic(s)
	char *s;

		Abort the program by printing a panic message including string "s"
		on stderr, flushing stdout and stderr, calling cleanup and exiting.

	_abort()
		By defining _abort to call panic, entering control-C while using
		stdio will cause the program to abort, executing your cleanup
		routines.  Also note that Manx sdb calls _abort when the user
		requests an exit, so your cleanup routines will be executed then
		as well.
*/

#include <exec/memory.h>
#include <stdio.h>

struct _clean 
{
	int (*function)();
	struct _clean *next;
} *cleanlist = NULL;

/* add_cleanup
 * given a function, add it to a list of functions to call when cleanup
 * is executed
 */
add_cleanup(function)
int (*function)();
{
	struct _clean *ptr;

	ptr = AllocMem(sizeof(struct _clean), MEMF_PUBLIC);
	if(!ptr)
		return 0;
	ptr->function = function;
	ptr->next = cleanlist;
	cleanlist = ptr;
}

/* cleanup
 * call all the functions that were passed as arguments to add_cleanup
 * this run
 */
cleanup()
{
	struct _clean *ptr;
	int (*f)();

	while(cleanlist) 
	{
		/* locate the next cleanup function and get the function pointer */
		ptr = cleanlist;
		cleanlist = cleanlist->next;
		f = ptr->function;

		/* cleanup must clean up after itself */
		FreeMem(ptr, sizeof(struct _clean));

		/* execute the function */
		(*f)();
	}
}

/* panic - abort with an error message */

short panic_in_progress = 0;

panic(s)
char *s;
{
	fflush(stdout);
	fprintf(stderr,"panic: %s\n",s);
	fflush(stderr);
	if (!panic_in_progress)
	{
		cleanup();
		exit(10);
	}
	fprintf(stderr,"double panic!\n");
	exit(11);
}

_abort()
{
	panic("^C or other C library abort");
}
