/*
 *  This file is part of ixemul.library for the Amiga.
 *  Copyright (C) 1991, 1992  Markus M. Wild
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#define KERNEL
#include "ixemul.h"
#undef u
#undef ix
#include <hardware/intbits.h>

#undef DEBUG

#ifdef DEBUG
#define DP(a) kprintf a
#else
#define DP(a)
#endif

#define BASE_EXT_DECL
#define BASE_PAR_DECL	struct ixemul_base *ix,
#define BASE_PAR_DECL0	struct ixemul_base *ix
#define BASE_NAME	ix->ix_intui_base
#include <inline/intuition.h>

void
ix_close (struct ixemul_base *ixbase)
{
  int fd;
  struct ExecBase 	*SysBase =	*(struct ExecBase **)4;
  struct Task 		*me 	 =	SysBase->ThisTask;
  struct user 		*u	 =	(struct user *) me->tc_TrapData;
  struct Process	*child;
  struct user		*cu;
  struct Node		*dm, *ndm;	/* really struct death_msg * */

DP(("ix_close.\n"));
    
  RemIntServer (INTB_VERTB, & u->u_itimerint);  
#if later
#endif
  
  me->tc_Flags    = u->u_otask_flags;
  me->tc_Launch	  = u->u_olaunch;
  me->tc_Switch   = u->u_oswitch;
  FreeSignal (u->u_sleep_sig);

  /* already reset the trap vector here. It's better to get an alert, than
   * to loop infinitely if one of the following functions should crash */
  me->tc_TrapCode = u->u_otrap_code;

  /* close all files */
  for (fd = 0; fd < NOFILE; fd++) 
    if (u->u_ofile[fd]) syscall (SYS_close, fd);

  CloseDevice ((struct IORequest *) u->u_time_req);
  syscall (SYS_DeleteExtIO, u->u_time_req);
  
  if (u->u_startup_cd != (BPTR) -1) __unlock (CurrentDir (u->u_startup_cd));
  
  syscall (SYS_DeletePort, u->u_sync_mp);
  DeleteInterruptPort (u->u_async_mp);

  /* have to make sure that no child is trying to manipulate our process
   * lists as well */
  ix_lock_base ();
  
  for ((child = u->p_cptr) && (cu = (struct user *) (child->pr_Task.tc_TrapData));
       child;
       (child = cu->p_osptr) && (cu = (struct user *) (child->pr_Task.tc_TrapData)))
    cu->p_pptr = (struct Process *) 1;

  u->p_cptr = 0;
  
  for (dm  = (struct Node *) u->p_zombies.mlh_Head;
       ndm = dm->ln_Succ;
       dm  = ndm)
    kfree (dm);

  ix_unlock_base ();

  FreeSignal (u->p_zombie_sig);

  all_free ();

  /* delay this until here, since the above called functions need access
   * to the user area. */
  me->tc_TrapData = u->u_otrap_data;

  kfree (u);
}
