/*
 *
 * Real-Time and Multimedia Systems Laboratory
 * Copyright (c) 2000 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Real-Time and Multimedia Systems Laboratory
 *  Attn: Prof. Raj Rajkumar
 *  Electrical and Computer Engineering, and Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 *  or via email to raj@ece.cmu.edu
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 *
 *
 */

/* $Author: dionisio $	 
 * $Date: 2001/05/14 18:13:47 $
 * $Id: rcl_syscall.c,v 1.1 2001/05/14 18:13:47 dionisio Exp $
 * 
 * rcl_syscall.c
 */

#define __NO_VERSION__

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/smp_lock.h> /* for lock_kernel */
#include <linux/wrapper.h> /*for sleeping and waking processes*/

#include <rk/rk_linux.h>
#include <rk/rk_error.h>
#include <rk/rk.h>

#include "rclmodule.h"



/*
 * check what is resistered in rs_proc_list
 */
inline void rs_proc_list_pid(struct rs_proc_list* rs_proc){
  if( rs_proc == NULL){
    printk("rs_proc_list_pid: ERROR\n");
    return;
  }
  printk(" (%d, %s)", rs_proc->rs_proc_pid, rs_proc->rs_proc_task->comm);
}


/*
 * helper function used by sys_*fork_trappers
 */
static inline int is_child_alive(int child_pid){
  if(child_pid != current->p_cptr->pid ||
     current->p_cptr->state == TASK_ZOMBIE ||
     current->p_cptr->flags & PF_EXITING){
    return 1;
  }
  else 
    return 0;
}



/********************************************************************
 * sytem call trapper functions
 ********************************************************************/

asmlinkage int 
sys_exit_trapper(int value){
  pre_exit_check();
  return sys_exit_call(value);
}



asmlinkage int 
sys_fork_trapper(struct pt_regs regs){
  int  user_id, child_pid;

  user_id =  getuid_call();
  if(pre_fork_check(user_id, current->pid) == -EINTR)
    return -EINTR;
  
  /* Call original sys_fork */
  child_pid = sys_fork_call(regs); 

  /* check if child is still alive */
  if(!is_child_alive(child_pid))
    return child_pid;
  
  post_fork_check(user_id, child_pid); 

  /* 
   *    /W/RK/linux/fs/proc/array.c for proc outputs.
   */

  /* todo: make this into an function so modules can use this call */
  /* struct task_struct *tsk; */
  /* tsk = __rk_find_process_by_pid(child_pid); */
  
  return child_pid;
}




/* TODO
 * probably should merge some of sys_clone_trapper and sys_fork_trapper...
 */
asmlinkage int 
sys_clone_trapper(struct pt_regs regs){
  int user_id, child_pid;

  user_id =  getuid_call();
  if(pre_fork_check(user_id, current->pid) == -EINTR)
    return -EINTR;
  
  /* Call original sys_fork */
  child_pid = sys_clone_call(regs); 

  /* check if child is still alive */
  if(!is_child_alive(child_pid))
    return child_pid;
  
  post_fork_check(user_id, child_pid);

  /* 
   *    /W/RK/linux/fs/proc/array.c for proc outputs.
   */

  /* todo: make this into an function so modules can use this call */
  /* struct task_struct *tsk; */
  /* tsk = __rk_find_process_by_pid(child_pid); */
  
  return child_pid;
}





/* todo
 * probably should merge some of sys_vfork_trapper and sys_fork_trapper...
 */
asmlinkage int 
sys_vfork_trapper(struct pt_regs regs){
  int user_id, child_pid;

  user_id =  getuid_call();
  if(pre_fork_check(user_id, current->pid) == -EINTR)
    return -EINTR;
  
  /* Call original sys_vfork */
  child_pid = sys_vfork_call(regs); 

  /* check if child is still alive */
  if(!is_child_alive(child_pid))
    return child_pid;

  post_fork_check(user_id, child_pid);

  /* 
   *    /W/RK/linux/fs/proc/array.c for proc outputs.
   */

  /* todo: make this into an function so modules can use this call */
  /* struct task_struct *tsk; */
  /* tsk = __rk_find_process_by_pid(child_pid); */
  
  return child_pid;
}



/*
 * Couldn't forward to sys_execve like other system calls. 
 * I had to re-implement sys_execve here. (copied from process.c)
 * I think the problem is that sys_execve changes,
 * the memory/register contents before returning....
 */
asmlinkage int 
sys_execve_trapper(struct pt_regs regs){
	int error; 
	int uid;
	char * filename;
	
	lock_kernel();
	filename = getname((char *) regs.ebx);


	uid = getuid_call();

	pre_execve_check(uid, filename);

	
	error = PTR_ERR(filename);
	if (IS_ERR(filename))
		goto out;
	error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);

	if (error == 0)
		current->flags &= ~PF_DTRACE;
	putname(filename);
out:
	unlock_kernel();
	return error;
}



/*
asmlinkage rk_reserve_t cpu_reserve_create_trapper(rk_resource_set_t rs,
						   cpu_reserve_attr_t cpu_attr)
{
  
  return sys_cpu_reserve_create(rs, cpu_attr);
}
*/

