#include <9pm/u.h>
#include <9pm/libc.h>

#define	NEXIT	33

static Lock onexlock;
static struct
{
	void	(*f)(void);
	int	pid;
}onex[NEXIT];

atexit(void (*f)(void))
{
	int i;

	lock(&onexlock);
	for(i=0; i<NEXIT; i++)
		if(onex[i].f == 0) {
			onex[i].pid = getpid();
			onex[i].f = f;
			unlock(&onexlock);
			return 1;
		}
	unlock(&onexlock);
	return 0;
}

void
atexitdont(void (*f)(void))
{
	int i, pid;

	pid = getpid();
	for(i=0; i<NEXIT; i++)
		if(onex[i].f == f && onex[i].pid == pid)
			onex[i].f = 0;
}

/*
 * The Plan 9 loaders don't realize they need main until they
 * get _main out of the system libc.  At that point, they've 
 * finished with our libc, and won't look there again.
 * It won't surprise me if the Unix loaders have this problem too.
 * We need to coerce the loader into loading main when
 * it passes through our libc.  We do this by assuming everyone
 * calls exits.  Here's how.
 */
extern ulong _pm_gross_hack;

void
exits(char *s)
{
	int i, pid;
	void (*f)(void);

_pm_gross_hack = 1;
	pid = getpid();
	for(i = NEXIT-1; i >= 0; i--)
		if((f = onex[i].f) && pid == onex[i].pid) {
			onex[i].f = 0;
			(*f)();
		}
	_exits(s);
}


syntax highlighted by Code2HTML, v. 0.9.1