/*
Auto:		sc <file>
*/

/* $Revision Header built automatically *************** (do not edit) ************
**
** © Copyright by GuntherSoft
**
** File             : SnakeSYS:CPrgs/Utils/Touch.c
** Created on       : Monday, 26.07.93 22:15:08
** Created by       : Kai Iske
** Current revision : V1.1
**
**
** Purpose
** -------
**   - Small touch command which will create a file, if it doesn`s
**     exists yet.
**
** Revision V1.1
** --------------
** created on Wednesday, 08.12.93 22:04:39  by  Kai Iske.   LogMessage :
**   - Reduced stack usage
**   - Reduced executable size
**   - Recompiled using SAS 6.50
**   - Added CTRL-C checking
**
** Revision V1.0
** --------------
** created on Monday, 26.07.93 22:15:08  by  Kai Iske.   LogMessage :
**     --- Initial release ---
**
*********************************************************************************/
#define REVISION "1.1"
#define REVDATE  "08.12.93"
#define REVTIME  "22:04:39"
#define AUTHOR   "Kai Iske"
#define VERNUM   1
#define REVNUM   1


#include	<string.h>
#include	<stdlib.h>
#include	<exec/types.h>
#include	<exec/memory.h>
#include	<dos/dos.h>
#include	<dos/exall.h>
#include	<proto/exec.h>
#include	<proto/dos.h>




/**********************************************************************/
/*                           Version String                           */
/**********************************************************************/
static const char *MyVer	= "$VER: Touch "REVISION" ("REVDATE")\0";




/**********************************************************************/
/*                  Template for Commandline Parsing                  */
/**********************************************************************/
static char *Template	= "FILES/M/A";
enum	{FILE_ARG, LAST_ARG};


/**********************************************************************/
/*                       The small main program                       */
/**********************************************************************/
ULONG __saveds main(void)
{
	struct	ExecBase	*SysBase;
	struct	DosLibrary	*DOSBase;
	struct	Process		*MyProc;
	struct	RDArgs		*RDArgs;
	struct	ExAllControl	*EAC;
	struct	ExAllData	*EAD;
	struct	DateStamp	DS;
	APTR	*EAB,
		*Args;
	BPTR	OutHandle,
		TouchFile;
	char	**FileNameList	= NULL,
		*MainBuffer,
		*FileName,
		*Pattern,
		*TouchName;
	WORD	FileNameType;
	ULONG	MySig;
	BOOL	GoOn,
		Breaked		= FALSE;

		// Get Base of Exec

	SysBase	= *((struct ExecBase **)0x4L);

		// Don`t start from WB

	MyProc	= (struct Process *)FindTask(NULL);

	if(!MyProc->pr_CLI)
	{
		struct	WBStartup	*Msg;

		WaitPort(&MyProc->pr_MsgPort);
		Msg	= (struct WBStartup *)GetMsg(&MyProc->pr_MsgPort);
		Disable();
		ReplyMsg((struct Message *)Msg);
		return(0);
	}

		// Get DOSBase

	if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0)))
		return(20);

		// Get handle to Output

	OutHandle = Output();

		// Check for System we`re running on

	if(((struct Library *)SysBase)->lib_Version < 37)
	{
		Write(OutHandle, "You must use KickStart 2.04 (37.175) or higher for Touch\n", 55);
		CloseLibrary((struct Library *)DOSBase);
		return(20);
	}

		// Get current DateStamp

	DateStamp(&DS);


		// Get buffer for filename etc.

	if((MainBuffer = AllocVec((1024 * 3), MEMF_CLEAR)))
	{
			// Set up buffers

		FileName	= MainBuffer;
		Pattern		= (FileName + 1024);
		TouchName	= (Pattern + 1024);

			// Get Buffer for arguments

		if((Args = AllocVec((LAST_ARG * sizeof(ULONG)), MEMF_CLEAR)))
		{
				// Parse Commandline

			if((RDArgs = ReadArgs(Template, (LONG *)Args, NULL)))
			{
					// Get buffer for ExAll

				if((EAB = AllocVec((sizeof(struct ExAllData) * 20), MEMF_CLEAR)))
				{
						// Get ExAllControl Structure

					if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
					{
							// Get pointers to FileNames passed

						FileNameList = Args[FILE_ARG];

							// Loop for all filenames

						while(FileNameList && *FileNameList && !Breaked)
						{
								// Check for CTRL-C

							MySig	= CheckSignal(SIGBREAKF_CTRL_C);
							if(!(MySig & SIGBREAKF_CTRL_C))
							{
									// Copy current filename

								strcpy(FileName, *FileNameList);

									// Create pattern

								if((FileNameType = ParsePatternNoCase(FilePart(FileName), Pattern, 512)) != -1)
								{
										// Check pattern type

									if(FileNameType)
									{
											// Real pattern. Remove trailing name

										*(PathPart(FileName)) = '\0';

											// Try to get lock to directory

										if((TouchFile = Lock(FileName, ACCESS_READ)))
										{
												// Set up ExAllControl

											EAC->eac_LastKey	= 0;
											EAC->eac_MatchString	= Pattern;
											EAC->eac_MatchFunc	= NULL;

											do
											{
													// Check for CTRL-C

												MySig	= CheckSignal(SIGBREAKF_CTRL_C);
												if((MySig & SIGBREAKF_CTRL_C))
													Breaked = TRUE;

													// Loop directory

												GoOn = ExAll(TouchFile, (struct ExAllData *)EAB, (108*20), ED_NAME, EAC);

													// Error occured ???

												if((!GoOn) && (IoErr() != ERROR_NO_MORE_ENTRIES))
													PrintFault(IoErr(), "Touch ");

													// End of dir reached ;

												if(EAC->eac_Entries == 0)
													GoOn = FALSE;
												else if(!Breaked)
												{
														// Get buffer to ExAll Buffer

													EAD = (struct ExAllData *)EAB;

													do
													{
															// Check for CTRL-C

														MySig	= CheckSignal(SIGBREAKF_CTRL_C);
														if((MySig & SIGBREAKF_CTRL_C))
															Breaked = TRUE;
														else
														{

																// Clear Touchname and create new one

															TouchName[0]	= '\0';
															AddPart(TouchName, FileName, 512);
															AddPart(TouchName, EAD->ed_Name, 512);

																// Set new date

															SetFileDate(TouchName, &DS);

																// Loop for entries

															EAD = EAD->ed_Next;
														}
													} while(EAD && !Breaked);
												}
											} while(GoOn);

												// UnLock directory

											UnLock(TouchFile);
										}
									}
									else
									{
											// File to be touched there ???

										if((TouchFile = Lock(FileName, ACCESS_READ)))
										{
												// Unlock it

											UnLock(TouchFile);

												// ... and set filedate

											SetFileDate(FileName, &DS);
										}
											// Otherwise create new file

										else if((TouchFile = Open(FileName, MODE_NEWFILE)))
											Close(TouchFile);
									}
								}
								else
								{
									PrintFault(IoErr(), "Touch ");
									FileNameList = NULL;
								}
									// Loop for files

								FileNameList++;
							}
							else
								Breaked = TRUE;
						}

						FreeDosObject(DOS_EXALLCONTROL, EAC);
					}
					else
						PrintFault(IoErr(), "Touch ");

					FreeVec(EAB);
				}
				else
					FPuts(OutHandle, "Touch : Buffer for Directory Scan could not be allocated\n");

				FreeArgs(RDArgs);
			}
			else
				PrintFault(IoErr(), "Touch ");

			FreeVec(Args);
		}
		else
			FPuts(OutHandle, "Touch : Buffer for Commandline could not be allocated\n");

		FreeVec(MainBuffer);
	}
	else
		PrintFault(ERROR_NO_FREE_STORE, "Touch ");

		// Display break status if needed

	if(Breaked)
		FPuts(OutHandle, "Touch : ^C...\n");

		// Close DOS

	CloseLibrary((struct Library *)DOSBase);

		// Return appropriate code

	if(FileNameList)
		return(0);
	else
		return(20);
}