/*
**	$RCSfile: cleanramdisk.c,v $
**	$Filename: CleanRamDisk.c $
**	$Revision: 2.3 $
**	$Date: 1994/08/21 18:56:15 $
**
**	vdisk.device support command CleanRamdisk (version 3.4)
**	
**	(C) Copyright 1993-2002 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 ULONG __saveds main(void);
#ifdef __SASC
void __regargs __chkabort(void);
#endif

static UBYTE template[] = "DEVICE,UNIT/K/N,NOFREECHIP/S,REBUILD/S,FREEBOOT/S,FORCE/S";
static UBYTE version[] = "$VER: CleanRamDisk 3.4 (14.12.2002)";

#define OPT_DEVICE	0
#define OPT_UNIT	1
#define OPT_NOFREECHIP	2
#define OPT_REBUILD	3
#define OPT_FREEBOOT	4
#define	OPT_FORCE	5
#define OPTMAX		6


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

  LONG opts[OPTMAX];

  ULONG mode = 0, rc = 0;
  LONG unit = 0, error;
  STRPTR errormsg;
  BOOL freeboot = FALSE;

  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));
    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)
      { handler = ((struct FileLock *)BADDR(argLock))->fl_Task;
        dlist = LockDosList(LDF_DEVICES|LDF_READ);
        while (dlist = NextDosEntry(dlist, LDF_DEVICES))
        { if (handler == dlist->dol_Task)
	  { 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_FREEBOOT]) freeboot = TRUE;
    if (opts[OPT_REBUILD]) mode |= VDCF_REBUILD;
    if (opts[OPT_NOFREECHIP] == NULL) mode |= VDCF_FREECHIP;
    if (opts[OPT_FORCE]) mode |= VDCF_FORCE;

    if (opts[OPT_UNIT]) 
    { unit = *(ULONG *)opts[OPT_UNIT];
      if (unit < 0 || unit >= VD_NUMUNITS)
      { Printf("Invalid unit number %ld\n", unit);
        clearall();
        return(20);
      }
    }
    if (opts[OPT_DEVICE])
    {
      UBYTE  *colon;
      struct DosList  *dlist;
      struct FileSysStartupMsg  *vdstartup;
      STRPTR fssmdev;

      unit = -1;
      if (colon = (UBYTE *)strchr((const char *)opts[OPT_DEVICE],':')) *colon = (UBYTE)0;
      dlist = LockDosList(LDF_DEVICES|LDF_READ);
      if (dlist = FindDosEntry(dlist,(STRPTR)opts[OPT_DEVICE],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);
    }
    if (unit == -1)
    { Printf(errormsg, (STRPTR)opts[OPT_DEVICE]);
      clearall();
      return(20);
    }
    FreeArgs(myrda);
    myrda = NULL;
  }

  if (!(error = OpenDevice(VD_NAME, -1L, &vdio, 0L)))
  { VDiskBase = (struct VD_Dev *)vdio.io_Device;
    if (error = CleanVDisk(unit, mode)) 
    { PrintError("Couldn't clean VDisk unit %ld : Error %ld\n", unit, error);
      rc = 10;
    }
    else if (freeboot) FreeVBlocks(unit, 0, 2);
    CloseDevice(&vdio);
  }     
  else 
  { PrintError("Couldn't open vdisk.device : Error %ld\n", error);
    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 *)"CleanRamDisk";
    ErrStruct.es_TextFormat = (UBYTE *)fmt;
    ErrStruct.es_GadgetFormat = (UBYTE *)"OK";
    return(EasyRequestArgs( 0L, &ErrStruct, 0L, args));
}

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
