/*
**	$RCSfile: deleteramdisk.c,v $
**	$Filename: DeleteRamDisk.c $
**	$Revision: 2.3 $
**	$Date: 1994/08/21 20:30:07 $
**
**	vdisk.device support command DeleteRamdisk (version 3.0) 
**	
**	(C) Copyright 1993-2001 by Etienne Vogt
*/

#include <exec/io.h>
#include <exec/alerts.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <dos/rdargs.h>
#include <workbench/startup.h>
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <stdlib.h>
#include <string.h>
#include "vdisk.h"
#include "vdisk_protos.h"
#include "vdisk_pragmas.h"

struct VD_Dev	*VDiskBase;
struct ExecBase *SysBase;
struct IntuitionBase *IntuitionBase;
static struct WBStartup *wbmsg;
static struct RDArgs	*myrda;
static struct IORequest vdio;

static void clearall(void);
static int ErrorReq(APTR fmt, ...);
static int ErrorReqArgs(APTR fmt, APTR args);
static int PrintError(APTR fmt, ...);
static int DeleteReq(APTR fmt, ...);
static ULONG __saveds main(void);
#ifdef __SASC
void __regargs __chkabort(void);
#endif

static UBYTE template[] = "DEVICE,UNIT/K/N";
static UBYTE version[] = "$VER: DeleteRamDisk 3.0 (13.8.2001)";
char devname[80];

#define OPT_DEVICE	0
#define OPT_UNIT	1
#define OPTMAX		2


static ULONG __saveds main(void)	/* No startup code */
{
  struct Process *myproc;

  LONG opts[OPTMAX];

  ULONG rc = 0;
  LONG unit = 0, error;
  STRPTR errormsg;
  BOOL inhibit = TRUE;

  SysBase = *(struct ExecBase **)4;
  DOSBase = NULL;
  IntuitionBase = NULL;
  VDiskBase = NULL;
  wbmsg = NULL;
  myrda = NULL;

  myproc = (struct Process *)FindTask(NULL);
  if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37)) == NULL)
  { Alert(AT_Recovery|AG_OpenLib|AO_DOSLib);
    clearall();
    return(100);
  }
  if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)) == NULL)
  { Alert(AT_Recovery|AG_OpenLib|AO_Intuition);
    clearall();
    return(100);
  }
  if (!(myproc->pr_CLI))
  { WaitPort(&(myproc->pr_MsgPort));
    wbmsg = (struct WBStartup *)GetMsg(&(myproc->pr_MsgPort));
    strcpy(devname, "VD0:");
    if (wbmsg->sm_NumArgs == 2)
    {
      BPTR argLock;
      struct MsgPort *handler;
      struct DosList *dlist;
      struct FileSysStartupMsg  *vdstartup;
      STRPTR fssmdev;

      unit = -1;
      if (argLock = (wbmsg->sm_ArgList[1]).wa_Lock)
      { if (handler = ((struct FileLock *)BADDR(argLock))->fl_Task)
        { dlist = LockDosList(LDF_DEVICES|LDF_READ);
          while (dlist = NextDosEntry(dlist, LDF_DEVICES))
          { if (handler == dlist->dol_Task)
	    { strcpy(devname, (const char *)BADDR(((struct DeviceNode *)dlist)->dn_Name) + 1);
	      strcat(devname, ":");
	      vdstartup = BADDR(((struct DeviceNode *)dlist)->dn_Startup);
              fssmdev = (UBYTE *)BADDR(vdstartup->fssm_Device) + 1;
              if (TypeOfMem(fssmdev) && !strcmp((const char *)fssmdev, VD_NAME)) unit = vdstartup->fssm_Unit;
	      break;
	    }
	  }
	  UnLockDosList(LDF_DEVICES|LDF_READ);
	}
      }
    }
    if (unit == -1)
    { ErrorReq("Selected object is not a VDisk unit");
      clearall();
      return(20);
    }
  }
  else
  { memset((char *)opts, 0, sizeof(opts));
    if ((myrda = ReadArgs(template, opts, NULL)) == NULL)
    { PrintFault(IoErr(),NULL);
      clearall();
      return(20);
    }
    if (opts[OPT_DEVICE] == NULL && opts[OPT_UNIT] == NULL) opts[OPT_DEVICE] = (LONG)"VD0:";
    if (opts[OPT_UNIT]) 
    { unit = *(ULONG *)opts[OPT_UNIT];
      inhibit = FALSE;
      if (unit < 0 || unit >= VD_NUMUNITS)
      { Printf("Invalid unit number %ld\n", unit);
        clearall();
        return(20);
      }
    }
    else
    {
      STRPTR colon, fssmdev;
      struct DosList  *dlist;
      struct FileSysStartupMsg  *vdstartup;

      unit = -1;
      if ((colon = (UBYTE *)strchr((const char *)opts[OPT_DEVICE],':')) && colon - (STRPTR)opts[OPT_DEVICE] < 79)
      { strncpy(devname, (const char *)opts[OPT_DEVICE], colon - (STRPTR)opts[OPT_DEVICE]);
	dlist = LockDosList(LDF_DEVICES|LDF_READ);
	if (dlist = FindDosEntry(dlist, (STRPTR)devname, LDF_DEVICES))
	{ vdstartup = BADDR(((struct DeviceNode *)dlist)->dn_Startup);
          fssmdev = (UBYTE *)BADDR(vdstartup->fssm_Device) + 1;
          if (TypeOfMem(fssmdev) && !strcmp((const char *)fssmdev, VD_NAME)) unit = vdstartup->fssm_Unit;
          else errormsg = "Device %s is not a vdisk unit\n";
	}
        else errormsg = "Device %s is not mounted\n";
        UnLockDosList(LDF_DEVICES|LDF_READ);
	strcat(devname, ":");
      }
      else errormsg = "Invalid device name %s\n";
    }
    if (unit == -1)
    { Printf(errormsg, (STRPTR)opts[OPT_DEVICE]);
      clearall();
      return(20);
    }
    FreeArgs(myrda);
    myrda = NULL;
  }

  if (wbmsg) if (DeleteReq("OK to delete device %s ?\n", devname) == 0)
  { clearall();
    return(10);
  }

  if (inhibit)
  { if (Inhibit(devname, DOSTRUE) == DOSFALSE)
    { PrintError("Couldn't inhibit drive %s\n", devname);
      clearall();
      return(20);
    }
  }

  if (!(error = OpenDevice(VD_NAME, -1L, &vdio, 0L)))
  { VDiskBase = (struct VD_Dev *)vdio.io_Device;
    if (error = DeleteVDisk(unit)) 
    { PrintError("Couldn't delete VDisk unit %ld : Error %ld\n", unit, error);
      Inhibit(devname, DOSFALSE);
      rc = 10;
    }
    CloseDevice(&vdio);
  }     
  else 
  { PrintError("Couldn't open vdisk.device : Error %ld\n", error);
    if (inhibit) Inhibit(devname, DOSFALSE);
    rc = 20;
  }
  clearall();
  return(rc);
}

static int PrintError(APTR fmt, ...)
{
  if (wbmsg) return(ErrorReqArgs(fmt, &fmt + 1));
  else return(VPrintf(fmt, (ULONG *)(&fmt + 1)));
}

static int ErrorReq(APTR fmt, ...)
{
  return(ErrorReqArgs(fmt, &fmt +1));
}

static int ErrorReqArgs(APTR fmt, APTR args)
{
  struct EasyStruct ErrStruct;

    ErrStruct.es_StructSize = sizeof(struct EasyStruct);
    ErrStruct.es_Flags = 0;
    ErrStruct.es_Title = (UBYTE *)"DeleteRamDisk";
    ErrStruct.es_TextFormat = (UBYTE *)fmt;
    ErrStruct.es_GadgetFormat = (UBYTE *)"OK";
    return(EasyRequestArgs( 0L, &ErrStruct, 0L, args));
}

static int DeleteReq(APTR fmt, ...)
{
  struct EasyStruct ErrStruct;

    ErrStruct.es_StructSize = sizeof(struct EasyStruct);
    ErrStruct.es_Flags = 0;
    ErrStruct.es_Title = (UBYTE *)"DeleteRamDisk";
    ErrStruct.es_TextFormat = (UBYTE *)fmt;
    ErrStruct.es_GadgetFormat = (UBYTE *)"OK|Cancel";
    return(EasyRequestArgs( 0L, &ErrStruct, 0L, &fmt + 1));
}

static void clearall(void)
{
  if (myrda) FreeArgs(myrda);
  if (DOSBase) CloseLibrary((struct Library *)DOSBase);
  if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
  if (wbmsg)
  { Forbid();
    ReplyMsg((struct Message *)wbmsg);
  }
}

#ifdef __SASC
void __regargs __chkabort(void)
{
}
#endif
