#define __USE_SYSBASE

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/rdargs.h>
#include <dos/dosasl.h>
#include <dos/dosextens.h>
#include <support/types.h>
#include <support/exec.h>

#include <string.h>

#include <proto/exec.h>
#include <proto/dos.h>

#include "touch.rev.h"

#define DOS_NAME		"dos.library"
#define DOS_VERN 		37L

#define TEMPLATE		"FILE/M,ONEDATE/S,ALL/S,QUIET/S"

STATIC CONST TEXT VersionString[]=
	VERSION(PROG_NAME,PROG_VERSION,PROG_REVISION,PROG_DATE);

#define MSG_TOUCHED			"  Touched\n"
#define MSG_NOT_TOUCHED	"  Not Touched"

#define OPT_FILE		0
#define OPT_ONE			1
#define OPT_ALL			2
#define OPT_QUIET		3
#define OPT_COUNT		4

#define NAME_SIZE		32
#define PATH_SIZE		256

ULONG Touch(VOID)
{
	struct ExecBase *SysBase=*((struct ExecBase **)4);
	struct DosLibrary *DOSBase;

	STATIC CONST STRPTR NoArgs[]={"#?",NULL};

	LONG Opts[OPT_COUNT];
	ULONG TempRC,RC=RETURN_FAIL;
	CHAR FName[NAME_SIZE],*CurArg,**ArgPtr;
	BPTR CurrLock,OldLock;
	struct RDArgs *Args;
	struct AnchorPath *Anchor;
	struct DateStamp ALIGNED StampData;
	BOOL ErrOccured=FALSE;

	unless(DOSBase=(struct DosLibrary *)OpenLibrary(DOS_NAME,DOS_VERN))
	{
		SetResult2(ERROR_INVALID_RESIDENT_LIBRARY);
		goto InvalidDOS;
	}

	unless(Anchor=AllocVec(sizeof(struct AnchorPath)+PATH_SIZE,MEMF_CLEAR))
	{
		PrintFault(IoErr(),NULL);								/* Inform user */
		goto NoMemory;
	}

	clear(&Opts);															/* Clear out args buffer */
	unless(Args=ReadArgs(TEMPLATE,Opts,NULL))
	{
		PrintFault(IoErr(),NULL);								/* Inform user */
		goto NoArgs;
	}

	DateStamp(&StampData);
	ArgPtr=Opts[OPT_FILE] ? (STRPTR *)Opts[OPT_FILE] : (STRPTR *)NoArgs;
	while(CurArg=*ArgPtr++)
	{
		clear(Anchor);
		Anchor->ap_BreakBits=SIGBREAKF_CTRL_C;		/* Allow break */
		Anchor->ap_Strlen=PATH_SIZE;							/* We have a path buffer */
		TempRC=MatchFirst(CurArg,Anchor);
		while(TempRC==0)
		{
			strcpy(FName,Anchor->ap_Info.fib_FileName);
			if(Anchor->ap_Info.fib_DirEntryType>=0)
			{
				if(Opts[OPT_ALL])
				{
					if(!ftst(Anchor->ap_Flags,APF_DIDDIR))
						fset(Anchor->ap_Flags,APF_DODIR);
					fclr(Anchor->ap_Flags,APF_DIDDIR);
				}
				goto Next;
			}
			CurrLock=DupLock(Anchor->ap_Current->an_Lock);
			OldLock=CurrentDir(CurrLock);
			unless(Opts[OPT_ONE])
				DateStamp(&StampData);
			if(SetFileDate(FName,&StampData))
			{
				unless(Opts[OPT_QUIET])
				{
					PutStr(Anchor->ap_Buf);				/* Print path... */
					PutStr(MSG_TOUCHED);
				}
			}
			else
			{
				PutStr(Anchor->ap_Buf);				/* Print path... */
				PrintFault(IoErr(),MSG_NOT_TOUCHED);
				ErrOccured=TRUE;
			}
			CurrentDir(OldLock);
			UnLock(CurrLock);
Next:
			TempRC=MatchNext(Anchor);
		}
		if(TempRC==ERROR_NO_MORE_ENTRIES)
			RC=(ErrOccured ? RETURN_ERROR : RETURN_OK);
		else
		{
			PrintFault(TempRC,NULL);
			RC=(TempRC==ERROR_BREAK ? RETURN_WARN : RETURN_FAIL);
		}
		MatchEnd(Anchor);
		if(TempRC==ERROR_BREAK)
			break;
	}

	FreeArgs(Args);
NoArgs:
	FreeVec(Anchor);
NoMemory:
	CloseLibrary((struct Library *)DOSBase);
InvalidDOS:
	return(RC);
}
