/*
 *	Copyright © 1991 by S.R. & P.C.
 *
 *	Created: 28 Mar 1993
 *	Modified:	20 May 1993	11:43:01
 *
 * Make>> SC <file>.c
 * Make>> SLink Lib:Entry.o <file>.o LIB Lib:String.lib MAP <file>.map F,H,L,O,S,X NOICON VERBOSE SmallCode SmallData BATCH
 * Ma ke>> SLink Lib:Entry.o <file>.o LIB Lib:Startup.lib Lib:String.lib MAP <file>.map F,H,L,O,S,X NOICON VERBOSE SmallCode SmallData BATCH
 */

#include <Main.h>
#include <StringLib.h>

#include <Libraries/HardBlocks.h>
/*#include <pragmas/HardBlocks_pragmas.h>*/

#define MAXSTRINGLEN 255/2
#define MAXNUMARGS 64
#define MAXDEFAULTLEN 512/2

STRPTR Template = "DosDev/M/A,ExecDev,UnitNr/N";
#define ARG_DosDevA	0
#define ARG_ExecDev	1
#define ARG_UnitNr	2
#define ARG_ENDARG	3
STRPTR CliHelp = "RDBMount V1.0 [32m© 1993 S.R.[31m\n\
Usage: RDBMount <DosDevName> [ExecDevName] [ExecUnitNr]\n\
Default: ExecDevName = scsi.device ExecUnitNr = 0 or read Env \"RDBMount.DefOpts\"\n\
Use to mount DOS Dev from the RigidDiskBlock information stored on (HD) drive\n";

struct DosLibrary *DOSBase;
struct Library *UtilityBase;
struct Library *ExpansionBase;
struct Library *HardBlocksBase;

char *B2CStr( UBYTE *BStr, char Buff[]) 
{
	UBYTE i;

	for ( i = 0; i < *BStr; i++)
		{
			Buff[ i] = (BStr + 1)[ i];
		}
	Buff[ i] = '\0';

	return Buff;
}

BOOL IsMounted( char DosName[])
{
	struct DosList *DList;
	BOOL Found = FALSE;

	DList = LockDosList( LDF_DEVICES|LDF_READ);
	Found = (BOOL) FindDosEntry( DList, DosName, LDF_DEVICES);
	UnLockDosList( LDF_DEVICES|LDF_READ);

	return Found;
}

ULONG __asm Main(register __a0 APTR ArgV[], register __a1 struct WBStartup * WBenchMsg);
ULONG __asm __Main(register __d2 ULONG CmdLen, register __a2 STRPTR CmdPtr)
{
	struct Process *pp;
	ULONG RC = 1001;		/* assumle the worst */

	pp = (struct Process *) FindTask(0L);

	if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 34L))
		{
			if (DOSBase->dl_lib.lib_Version > 36)
				{
					APTR ArgV[MAXNUMARGS];
					struct RDArgs *RA;
					struct RDArgs *DefaultRDArgs;

					UtilityBase = DOSBase->dl_UtilityBase;
					if (RA = AllocDosObject(DOS_RDARGS, NULL))
						{
							memset(ArgV, 0, MAXNUMARGS * sizeof(APTR));
							RA->RDA_ExtHelp = CliHelp;
							/* first read default */
							/* getting the default string */
							if (DefaultRDArgs = AllocDosObject(DOS_RDARGS, NULL))
								{
									UBYTE Default[ MAXDEFAULTLEN] = "DosDev Dummy ExecDev scsi.device UnitNr 0";

									if ( (DefaultRDArgs->RDA_Source.CS_Length = GetVar("RDBMount.DefOpts", Default, MAXDEFAULTLEN - 1, 0L)) > 0)
										;
									else
										DefaultRDArgs->RDA_Source.CS_Length = strlen( Default);
									{
										/* let ReadArgs() allocate neccesary buffer sinc I use diferrent RDArgs for Default and CLI opts */

										/* Ok I succefuly read a Default Option string now parse it */
										Default[DefaultRDArgs->RDA_Source.CS_Length++] = '\n';	/* this is need by ReadArgs() */
										Default[DefaultRDArgs->RDA_Source.CS_Length] = '\0';	/* this is need by ReadArgs() */
										DefaultRDArgs->RDA_Source.CS_Buffer = Default;
										DefaultRDArgs->RDA_Source.CS_CurChr = 0;
										DefaultRDArgs->RDA_Flags = RDAF_NOPROMPT;
										if (!ReadArgs(Template, (long *) ArgV, DefaultRDArgs))
											{
												PutStr("Error in Default:");
												PrintFault(IoErr(), NULL);
												memset(ArgV, 0, MAXNUMARGS * sizeof(APTR));
											}
										DefaultRDArgs->RDA_Source.CS_Buffer = NULL;	/* Now ReadArgs() from Command line */
										/* the ArgV is leaving unchanged: the second ReadArgs() take actual value as default */
									}
								}
							/* Let ReadArgs() allocate necessay buffer rather using stack space */
							if (ReadArgs(Template, (long *) ArgV, RA))
								{
									RC = Main(ArgV, NULL);
								}
							else
								{
									PrintFault(IoErr(), NULL);
									RC = 20;
								}
							FreeDosObject(DOS_RDARGS, RA);
							/* Free RDargs now I don't need the option value */
							if (DefaultRDArgs)
								FreeDosObject(DOS_RDARGS, DefaultRDArgs);
						}
				}
			else
				{
					Write(pp->pr_COS, "You need KickStart 2.0+\n", 24L);
					RC = 1000;
				}
			CloseLibrary((struct Library *) DOSBase);
		}

	return RC;
}

ULONG __asm Main( register __a0 APTR ArgV[], register __a1 struct WBStartup *WBenchMsg)
{
	ULONG RC = 20;	/* default :Don't find desired Partition */

	ExpansionBase = OpenLibrary( "expansion.library", 37L);

	if ( HardBlocksBase = OpenLibrary(HardBlocksName, HardBlocksVersion))
		{
			struct RigidDiskBlock rdb;

			if ( !(RC = LoadHardBlocks( &rdb, ArgV[ ARG_ExecDev], *(( ULONG *)ArgV[ ARG_UnitNr]))))
				{
					#define MAXMOUNT 10
					ULONG parmPkt[ MAXMOUNT][ 21 + 10];	/* WARN: this is a lenthg which can change */
					char DevNames[ MAXMOUNT][ 20];	/* mem string don't be lost until the mount */
					UBYTE MountCnt = 0;
					UBYTE i, j;
					char *Str;

					for ( i = 0, Str = ( (char **)ArgV[ ARG_DosDevA])[ 0]; Str && ( i < MAXMOUNT); i++, Str = ( (char **)ArgV[ ARG_DosDevA])[ i])
						{
							BOOL Found = FALSE;
							struct PartitionBlock *PB;
							char Buff[ MAXSTRINGLEN];
							char DosDevName[ MAXSTRINGLEN];

							strcpy( DosDevName, Str);
							{
								UBYTE l;
								if ( DosDevName[ l = (strlen( DosDevName) - 1)] == ':')
									DosDevName[ l] = '\0';
							}
							if ( !IsMounted( DosDevName))
								{
									for ( PB = (struct PartitionBlock *) rdb.rdb_PartitionList; PB && !Found; PB = (struct PartitionBlock *)PB->pb_Next)
										{
											B2CStr( PB->pb_DriveName, Buff);
				//							Printf( "Dos Name:\"%s\"\n", Buff);
				//							Printf("pb:%lx, next:%lx\n", PB, PB->pb_Next);
											if ( !Strnicmp( DosDevName, Buff, MAXSTRINGLEN))
												{
													strcpy( DevNames[ MountCnt], Buff);
													parmPkt[ MountCnt][ 0] = (ULONG)DevNames[ MountCnt];
													parmPkt[ MountCnt][ 1] = (ULONG)ArgV[ ARG_ExecDev];
													parmPkt[ MountCnt][ 2] = *( (ULONG *)ArgV[ ARG_UnitNr]);	/* unit number */
													parmPkt[ MountCnt][ 3] = 0;	/* OpenDevice flags */
													CopyMem( PB->pb_Environment, &parmPkt[ MountCnt][ 4], sizeof( PB->pb_Environment));
													Found = TRUE;
													MountCnt++;
												}
										}
									if ( !Found)
										Printf( "\"%s:\" not found.\n", DosDevName);
								}
							else
								{
									Printf( "\"%s:\" alredy mounted.\n", DosDevName);
								}
						}
					for ( j = 0; j < MountCnt; j++)
						{
							struct DeviceNode *DeviceNode;

							if ( DeviceNode = MakeDosNode( parmPkt[ j]))
								{
									if ( !AddDosNode( -128, ADNF_STARTPROC, DeviceNode))
										{
											Printf( "\"%s\" can't be Mounted\n", parmPkt[ j][ 0]);
										}
								}
						}
					FreeHardBlocks(&rdb);
				}
			else
				Printf( "Unable to Load RDB from \"%s\" %ld\n", ArgV[ ARG_ExecDev], *( (ULONG *)ArgV[ ARG_UnitNr]));
			CloseLibrary(HardBlocksBase);
		}
	else
		Printf( "Unable to open hardblocks.library V1+\n");

	CloseLibrary( ExpansionBase);

	return RC;
}
