#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syscall.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>


int main(int argc, char **argv)
{
   long long counter = 0;	/*  machine instruction counter */
   int wait_val;		/*  child's return value        */
   int pid;			/*  child's process id          */
   time_t start, finish;

   puts("Please wait");
   start = time(NULL);
   switch (pid = fork()) {
      case -1:
	 perror("fork");
	 break;
      case 0:			/*  child process starts        */
	 /* 
	  *  must be called in order to allow the
	  *  control over the child process
	  */
	 ptrace(PTRACE_TRACEME, 0, 0, 0);
	  
	 /*
	  *  executes the program and causes
	  *  the child to stop and send a signal 
	  *  to the parent, the parent can now
	  *  switch to PTRACE_SINGLESTEP   
	  */
	 argv++;
 	 execvp(argv[0], argv);
	 break;
	 /*  child process ends  */
      default:			/*  parent process starts       */
	 wait(&wait_val);
	 /*   
	  *   parent waits for child to stop at next 
	  *   instruction (execl()) 
	  */
	 while (wait_val == 1407) {
	    counter++;
	    if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0)
	       perror("ptrace");
	    /* 
	     *   switch to singlestep tracing and 
	     *   release child
	     *   if unable call error.
	     */
	    wait(&wait_val);
	    /*   wait for next instruction to complete  */
	 }
	 /*
	  * continue to stop, wait and release until
	  * the child is finished; wait_val != 1407
	  * Low=0177L and High=05 (SIGTRAP)
	  */
   }
   finish = time(NULL);
   printf("Number of machine instructions : %lld\nCompleted in %lu seconds\n", counter, (finish - start));
   return 0;
}
