/* Process tracing the old and icky way
   Copyright (C) 1991 Free Software Foundation

This file is part of the GNU Hurd.

The GNU Hurd is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.

The GNU Hurd is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with the GNU Hurd; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by Michael I. Bushnell.  */

/* The basic strategy is to have ptrace requests handled by the child
   with the alix_ptrace call.  This is all quite slow, but nobody expects
   ptrace to be fast.  */

int
ptrace (void *ap, int *ret1, int *ret2)
{
  struct
    {
      int request;
      int pid;
      int addr;
      int data;
    }
  *args = ap;
  sigthread_t sigthd;
  int ischld;
  int err;
  int ret;
  
  if (request == PT_TRACE_ME)
    {
      beingtraced = 1;
      proc_mark_traced (procserver);
      err = 0;
    }
  else 
    {
      err = h2ae (proc_getsigport (procserver, args->pid, &sigthd, &ischld));
      if (err)
	return err;
      if (ischld)
	err = h2ae (alix_ptrace (sigthd, args->request, 
				 args->addr, args->data, ret1));
      else
	err = ESRCH;
      mach_port_deallocate (mach_task_self (), sigthd);
    }
  return err;
}


/* Called inside sig thread when we get a ptrace request */
alix_ptrace (mach_port_t sigthd,
	     int request,
	     int addr,
	     int data,
	     int *ret)
{
  switch (request)
    {
    case PT_READ_I:
    case PT_READ_D:
      return copyin (addr, ret, sizeof (int)) ? POSIX_EIO : POSIX_SUCCESS;

    case PT_WRITE_I:
    case PT_WRITE_D:
      return copyout (&data, addr, sizeof (int)) ? POSIX_EIO : POSIX_SUCCESS;
      
    case PT_CONTINUE:

    case PT_KILL:

    case PT_STEP:


    case PT_READ_U:

    case PT_WRITE_U:

    default:
      return POSIX_EIO;
    }
  return 0;
}
