/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <mycroft@virgaria.org> wrote this file. As long as you retain this notice
 * you can do whatever you want with this stuff. If we meet some day, and you
 * think this stuff is worth it, you can buy me a beer in return Patrick MARIE. 
 * ----------------------------------------------------------------------------
 */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/sysproto.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>

#if (__FreeBSD_version > 500000)

#define F_A	struct thread *p
#define P_FLAG	p->td_proc->p_flag

#elif (__FreeBSD_version > 400000)

#define F_A	struct proc *p
#define P_FLAG p->p_flag

#else
#error "Not supported."
#endif

#define NODE(MOD,ARGNUM) \
	static struct sysent old_##MOD##_sysent; \
	static int \
	new_##MOD(F_A, struct MOD##_args *uap) \
	{ \
		if((P_FLAG & P_JAILED) == P_JAILED) { \
			return(ENOENT); \
		} \
	return(MOD(p, uap)); \
	} \
	static struct sysent new_##MOD##_sysent = { \
		ARGNUM, \
		(sy_call_t *)new_##MOD \
	}; \
	

#define REPLACE(MOD)	\
	old_##MOD##_sysent = sysent[SYS_##MOD]; \
	sysent[SYS_##MOD] = new_##MOD##_sysent;

#define UNREPLACE(MOD)	\
	sysent[SYS_##MOD] = old_##MOD##_sysent;

NODE(kldnext, 1)
NODE(kldstat, 2)
NODE(kldfind, 1)
NODE(kldfirstmod, 1)

static int
load (struct module *module, int cmd, void *arg)
{
	int error = 0;

	switch(cmd) {
	case MOD_LOAD :
		REPLACE(kldnext)
		REPLACE(kldstat)
		REPLACE(kldfind)
		REPLACE(kldfirstmod)

		printf ("syscall loaded.\n");
		break;
	case MOD_UNLOAD :
		UNREPLACE(kldnext)
		UNREPLACE(kldstat)
		UNREPLACE(kldfind)
		UNREPLACE(kldfirstmod)

		printf ("syscall unloaded.\n");
		break;
	default :
		error = EINVAL;
		break;
	}
	return error;
}

static moduledata_t syscall_mod = {
  "pan",
  load,
  NULL
};

DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);

