#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <err.h>

extern char *__progname;

/*
 * track forks and exits of a process by Peter Werner <peterw@ifost.org.au> 
 */

int
main(int argc, char **argv)
{
	pid_t pid;
	int kq, i;
	struct kevent ke;

	if (argc != 2)
		errx(1, "./%s <pid>", __progname);

	pid = atoi(argv[1]);

	kq = kqueue();
	if (kq == -1)
		err(1, "kq!");

	/* 
	 * we want notification of exits and forks as well as with children
	 */
	EV_SET(&ke, pid, EVFILT_PROC, EV_ADD,
	    NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK, 0, NULL);

	/*
	 * set the event 
	 */
	i = kevent(kq, &ke, 1, NULL, 0, NULL);
	if (i == -1)
		err(1, "proc kevent!");

	while (1) {

		memset(&ke, 0x00, sizeof(struct kevent));

		/*
		 * do a blocking kevent call till something happens
		 */
		i = kevent(kq, NULL, 0, &ke, 1, NULL);
		if (i == -1)
			err(1, "kevent!");

		if (ke.fflags & NOTE_FORK)
			printf("pid %d called fork()\n", ke.ident);

		if (ke.fflags & NOTE_CHILD)
			printf("pid %d has %d as parent\n", ke.ident,
			    ke.data);

		if (ke.fflags & NOTE_EXIT)
			printf("pid %d exited\n", ke.ident);
	
		if (ke.fflags & NOTE_EXEC)
			printf("pid %d called exec()\n", ke.ident);

		if (ke.fflags & NOTE_TRACKERR)
			printf("couldnt attach to child of %d\n", ke.ident);
	}

	return(0);
}
