/*
Auto:		sc <file> LINK NODEBUG NOSTRCONS OPT SINT NOSTACKCHECK DATA=NEAR STARTUP=cres PARM=REGISTER UTILLIB NOSTKCHK
*/

/* $Revision Header built automatically *************** (do not edit) ************
**
** © Copyright by GuntherSoft
**
** File             : SnakeSYS:CPrgs/Utils/Man.c
** Created on       : Friday, 16.07.93 18:00:23
** Created by       : Kai Iske
** Current revision : V1.2
**
**
** Purpose
** -------
**   - This is a man program, which may scan different directories
**     for man-pages. These directories are set within an ENV-VAR
**     called MANPATHS. Additionally a VIEWER may be set using
**     ENV-VAR MANVIEW (for plain ASCII) or MANVIEWAG (for
**     AMIGAGUIDE). THIS ONE`S PURE AND IN THE PUBLIC DOMAIN
**
** Revision V1.2
** --------------
** created on Tuesday, 27.07.93 15:20:51  by  Kai Iske.   LogMessage :
**   - Used MAN as a keyword for the template which prevented MAN
**     to accept inputs like "man man".
**
** Revision V1.1
** --------------
** created on Monday, 26.07.93 17:42:32  by  Kai Iske.   LogMessage :
**   - Accidentially called Exit() instead of exit(), which
**     prevented the program to pass the cleanup code of SAS.
**     So a lock to the directory was kept and the shell could
**     never been left.............
**
** Revision V1.0
** --------------
** created on Friday, 16.07.93 18:00:23  by  Kai Iske.   LogMessage :
**  -*-  changed on Saturday, 17.07.93 16:30:41  by  Kai Iske.   LogMessage :
**   - Man now searches for files that end up with .doc/.man/.guide
**     If a .guide file is found, the second Viewer (MANVIEWAG)
**     will be used to display the AmigaGuide viewer. Otherwise
**     the normal viewer (MANVIEW) will be used
**  -*-  created on Friday, 16.07.93 18:00:23  by  Kai Iske.   LogMessage :
**     --- Initial release ---
**
*********************************************************************************/
#define REVISION "1.2"
#define REVDATE  "27.07.93"
#define REVTIME  "15:20:51"
#define AUTHOR   "Kai Iske"
#define VERNUM   1
#define REVNUM   2

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


extern struct SysBase *SysBase;
extern struct WBStartUp *_WBenchMsg;


/**********************************************************************/
/*                             Prototypes                             */
/**********************************************************************/
char	*GetDir(char *NewName, char *OldName);



/**********************************************************************/
/*                           Version-String                           */
/**********************************************************************/
static char *Version = "$VER: Man "REVISION" ("REVDATE")\0";


/**********************************************************************/
/*                 Template for Command-Line parsing                  */
/**********************************************************************/
static char *Template	= "MANPAGE/A";
enum {MAN_ARG};



/**********************************************************************/
/*                       This is the main part                        */
/**********************************************************************/
void main(void)
{
	char	ManPaths[512];
	char	ViewCmd[512];
	char	ViewCmdAG[512];
	char	CheckDir[512];
	char	SearchName[512];
	char	FileName[130];
	struct	RDArgs		*RDArgs	= NULL;
	struct	ExAllControl	*EAC	= NULL;
	APTR	*Args;
	APTR	EAB			= NULL;
	char	*DirOffset		= ManPaths;
	char	Pattern[270];
	BPTR	TestLock;
	BPTR	OutHandle;
	BOOL	Found			= FALSE,
		GoOn;

		// Get Out Handle

	OutHandle = Output();

		// Check System we`re running on
		// Whoops, System checks are "done" by startup code anyway ;)

		// Don`t start from WB

	if(_WBenchMsg)
		exit(0);


		// Get buffer for Commandline parsing

	if((Args = AllocVec((MAN_ARG + 1)*sizeof(ULONG), MEMF_CLEAR)))
	{
			// Get structure for ExAll()

		if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
		{
				// Get buffer for ExAll()

			if((EAB = AllocVec(sizeof(struct ExAllData)*20, MEMF_CLEAR)))
			{
					// Try to parse commandline

				if((RDArgs = ReadArgs(Template, (LONG *)Args, NULL)))
				{
						// Try to get MANPATHS Env-Variable

					if(GetVar("MANPATHS", ManPaths, 256, GVF_GLOBAL_ONLY) >= 1)
					{
							// Try to get MANVIEW Env-Variable

						if(GetVar("MANVIEW", ViewCmd, 256, GVF_GLOBAL_ONLY) >= 1)
						{
								// Try to get MANVIEWAG Env-Variable

							if(GetVar("MANVIEWAG", ViewCmdAG, 256, GVF_GLOBAL_ONLY) >= 1)
							{
									// Set pattern for ExAll() search

								strcpy(SearchName, Args[MAN_ARG]);
								strcat(SearchName, "(.doc|.man|.guide)");

									// Parse the pattern

								if(ParsePatternNoCase(SearchName, Pattern, 270) != -1)
								{

										// Loop for all dirs and wait until file has been found

									while(!Found && DirOffset)
									{
											// Extract next directory from list

										DirOffset = GetDir(CheckDir, DirOffset);

											// Add "/" if neither "/", nor ":" end the directory

										if((CheckDir[strlen(CheckDir) - 1] != '/') && (CheckDir[strlen(CheckDir) - 1] != ':'))
											strcat(CheckDir, "/");

											// Directory available ???

										if((TestLock = Lock(CheckDir, ACCESS_READ)))
										{
												// Fill in ExAll structure

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

											do
											{
													// Do the scanning

												GoOn = ExAll(TestLock, EAB, (108*20), ED_NAME, EAC);

													// Error occured ???

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

													// End of dir reached ;

												if(EAC->eac_Entries == 0)
													GoOn = FALSE;
												else
												{
														// Get name of file

													strcpy(FileName, ((struct ExAllData *)EAB)->ed_Name);

														// Check extension to decide whether it`s an AmigaGuide file

													if(strcmp(&FileName[strlen(FileName) - 6], ".guide"))
														strcpy(SearchName, ViewCmd);
													else
														strcpy(SearchName, ViewCmdAG);

														// Append directory and FileName

													strcat(SearchName, " ");
													strcat(SearchName, CheckDir);

														// Copy Filename to place where the last quote used to reside

													strcat(SearchName, FileName);


														// Set flag that we`ve found the file

													Found = TRUE;
												}
											} while(GoOn);

												// Unlock Directory

											UnLock(TestLock);
										}
										else
										{
												// Display message

											FPuts(OutHandle, "Skipping directory; not existent : ");
											FPuts(OutHandle, CheckDir);
											FPuts(OutHandle, "\n");
										}
									}
								}
								else
									PrintFault(IoErr(), "Man ");
							}
							else
								PrintFault(IoErr(), "MANVIEWAG ");
						}
						else
							PrintFault(IoErr(), "MANVIEW ");
					}
					else
						PrintFault(IoErr(), "MANPATHS ");
				}
				else
					PrintFault(IoErr(), "Man ");
			}
			else
				FPuts(OutHandle, "Could not allocate buffer for ExAll()\n");
		}
		else
			FPuts(OutHandle, "Could not allocate structure for ExAll()\n");
	}
	else
		FPuts(OutHandle, "Could not allocate buffer for CommandLine Parsing\n");

	if(Args && RDArgs && !Found)
		strcpy(FileName, Args[MAN_ARG]);

	if(EAC)
		FreeDosObject(DOS_EXALLCONTROL, (void *)EAC);

	if(EAB)
		FreeVec(EAB);

	if(RDArgs)
		FreeArgs(RDArgs);

	if(Args)
		FreeVec(Args);

	if(Found)
	{
		SystemTags(SearchName, TAG_DONE);
		exit(0);
	}
	else if(Args && RDArgs)
	{
		FPuts(OutHandle, "Man-Pages not found for : ");
		FPuts(OutHandle, FileName);
		FPuts(OutHandle, "\n");
		exit(10);
	}
}





/**********************************************************************/
/*          Get portions from the Env-Var -> Next directory           */
/**********************************************************************/
char *GetDir(char *NewDir, char *OldDir)
{
	while(*OldDir == ' ')
		OldDir++;

	while((*OldDir != '\n') && (*OldDir != '\0') && (*OldDir != '|') && (*OldDir != ','))
		*NewDir++ = *OldDir++;

	*NewDir		= '\0';

	if(*OldDir == '\n' || *OldDir == '\0')
		OldDir = NULL;
	else
		OldDir++;

	return(OldDir);
}
