/* addlib.c -- Used to add more than one version of the same library
 *	       to the library list - *extremely handy tool*.
 *
 * Copyright (C) 1987 SDB.
 * Use at your own risk.
 *
 * SDB - For use in working on new versions of ArpLib, while keeping old.
 *
 *	If Exec finds a library node using the name requested, but with a
 *	version which is lower than the requested version, it does not
 *	abort the search, but continues searching for a library with the correct
 *	name and version.  This allows several libraries to be in memory at
 *	the same time, and to be correctly found by code which is looking for
 *	the correct version - NOTE: lower lib versions MUST BE added first.
 *
 *	Revised: KILLS environment if GREATER than version 11.
 *
 */

#include <exec/types.h>
#include <exec/resident.h>
#include <exec/libraries.h>
#include <exec/execbase.h>
#include <libraries/arpbase.h>

struct ArpBase *ArpBase, *FindName();
struct EnvironmentBase *EB;
extern struct ExecBase *SysBase;

ULONG LoadSeg();
VOID UnLoadSeg();
VOID RemLibrary();

main(argc, argv)
char **argv;
{
	ULONG 		segment;
	REGISTER UWORD *realptr;
	ULONG 		segsize;
	REGISTER struct Resident *res;
	REGISTER ULONG	i;
	int c;

	if (argc <= 1)
		printf("Usage: addlib <pathname>\n"),exit(120);

	++argv;

	segment = LoadSeg(*argv);
	if (segment == 0)
		printf("Can't find %s\n", *argv), exit(130);

	realptr = (UWORD *)(segment << 2);

	for (i = 0; i < 1000; i++, realptr++)
	{
		res = (struct Resident *)realptr;
		if (res->rt_MatchWord == RTC_MATCHWORD && res == res->rt_MatchTag)
			break;	/* Gotcha! */
	}
	res = (struct Resident *)realptr;

	if ( res->rt_MatchWord != RTC_MATCHWORD || res != res->rt_MatchTag)
	{
		printf("Can't find resident segment in first 2000 bytes!\n");
		UnLoadSeg(segment);
		exit(140);
	}
	/* Flush library if there is one of that name/version already on list */

	Forbid();
	ArpBase = (struct ArpBase *)(&SysBase->LibList);
	while ( ArpBase = FindName(ArpBase, "arp.library"))
		if (ArpBase->LibNode.lib_Version == res->rt_Version)
			break;

	if (ArpBase)
	{
		i = ArpBase->LibNode.lib_Version;
		/* FOLLOWING CODE IS DANGEROUS!!!! */
		EB = (struct EnvironmentBase *)ArpBase->EnvBase;
		if (i >= 12 && *EB->EnvSpace)
		{
			puts("Warning: Installed ArpLib has active an environment");
			puts("Are you sure you want to Expunge? (y/n)");
			c = getchar();
			if (c != 'y')
			{
				puts("ABORTED");
				UnLoadSeg(segment);
				Permit();
				exit(500);
			}
			*EB->EnvSpace = 0;	/* Kill environment */
		}
		if (ArpBase->LibNode.lib_OpenCnt)
		{
			printf("Warning: Version %ld of arplibrary has %d openers\n",
				i, ArpBase->LibNode.lib_OpenCnt);
			printf("Are you sure you want to Expunge and add? (y/n) ");
			c = getchar();
			if (c != 'y')
			{
				puts("ABORTED");
				UnLoadSeg(segment);
				Permit();
				exit(1000);
			}

			while (ArpBase->LibNode.lib_OpenCnt > 1)
				CloseLibrary(ArpBase);
		}
		if (ArpBase->LibNode.lib_OpenCnt)
			RemLibrary(ArpBase), CloseLibrary(ArpBase);
		else
			RemLibrary(ArpBase);
	}	
	InitResident(res, segment);
	Permit();
	puts("Added");
}
