/*
**	FixPath.c
**
**	Fix the current Process search patch list by faking a CLI
**
**	Copyright © 1990-1996 by Olaf `Olsen' Barthel
**		All Rights Reserved
**
**	:ts=4
*/

#ifndef _GLOBAL_H
#include "Global.h"
#endif

	// This is how a linked list of directory search paths looks like.

struct Path
{
	BPTR path_Next;	// Pointer to next entry
	BPTR path_Lock;	// The drawer in question; may be NULL
};

	/* ClonePath(BPTR StartPath):
	 *
	 *	Make a copy of the command search path attached to a
	 *	CLI process.
	 */

STATIC BPTR
ClonePath(BPTR StartPath)
{
	struct Path	*First,*Last,*List,*New;

	for(List = BADDR(StartPath), First = Last = NULL ; List ; List = BADDR(List->path_Next))
	{
		if(List->path_Lock)
		{
			if(New = AllocVec(sizeof(struct Path),MEMF_ANY))
			{
				if(New->path_Lock = DupLock(List->path_Lock))
				{
					New->path_Next = NULL;

					if(Last)
						Last->path_Next = MKBADDR(New);

					if(!First)
						First = New;

					Last = New;
				}
				else
				{
					FreeVec(New);
					break;
				}
			}
			else
				break;
		}
	}

	return(MKBADDR(First));
}

	/* AttachCLI(struct WBStartup *Startup):
	 *
	 *	Attach a valid CLI structure to the current process. Requires a
	 *	Workbench startup message whose command search path it will
	 *	duplicate.
	 */

VOID
AttachCLI(struct WBStartup *Startup)
{
	struct CommandLineInterface	*DestCLI;

		// Note: FreeDosObject can't free it, but the DOS
		//       process termination code can.

	if(DestCLI = AllocDosObjectTagList(DOS_CLI,NULL))
	{
		struct Process *Dest;
		struct MsgPort *ReplyPort;

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

		DestCLI->cli_DefaultStack = 4096 / sizeof(ULONG);

		Dest->pr_CLI	 = MKBADDR(DestCLI);
		Dest->pr_Flags 	|= PRF_FREECLI;			// Mark for cleanup

		Forbid();

		ReplyPort = Startup->sm_Message.mn_ReplyPort;

			// Does the reply port data point somewhere sensible?

		if(ReplyPort && (ReplyPort->mp_Flags & PF_ACTION) == PA_SIGNAL && TypeOfMem(ReplyPort->mp_SigTask))
		{
			struct CommandLineInterface	*SourceCLI;

				// Is there a CLI attached?

			if(SourceCLI = BADDR(((struct Process *)ReplyPort->mp_SigTask)->pr_CLI))
			{
					// Clone the other CLI data.

				DestCLI->cli_DefaultStack = SourceCLI->cli_DefaultStack;

				if(SourceCLI->cli_Prompt)
					SetPrompt((STRPTR)BADDR(SourceCLI->cli_Prompt));

				if(SourceCLI->cli_CommandDir)
					DestCLI->cli_CommandDir = ClonePath(SourceCLI->cli_CommandDir);
			}
		}

		Permit();
	}
}
