/*
 * Copyright 1988, 1989, 1990, 1991 Massachusetts Institute of Technology
 */
#ifdef DYNAEXT
#include "structs.h"
#include <dlfcn.h>
#include "../../GlibExt/GDyna.h"
#include "dynaext.h"
	
static DynaObj *topobj;

int numobjs, need_to_rebuild_extensions = 0;
typedef struct {
	char *the_name;
	void *ctrlfuncs;
	void *dofuncs;
} ExtenList;
ExtenList *extensions;

dyna_ext_ctrl(cmd, data)
	 int cmd;
	 caddr_t data;
{
	switch (cmd) {
	  case EXT_INIT:
	  case EXT_PREBUILD:
	  case EXT_POSTBUILD:
	  case EXT_PERIODIC:
		return 0;
		break;
	  case EXT_SHUTOFF:
		/* Close linked libraries */
		{
			DynaObj *curobj, *nextobj;
			curobj = topobj;
			while (curobj != (DynaObj *)NULL) {
				nextobj = curobj->next;
				destroydynaobj(curobj);
				curobj = nextobj;
			}
		}
		return 0;
		break;
	}
}

dyna_ext_dofuncs(msgsock, hostcommand, clinum)
	 int msgsock, clinum;
	 Galatea_packet *hostcommand;
{
	/* parm[1] switches the minor numbers */
	switch (hostcommand->parm[1]) {
	  case DYNA_LOAD:
		return (DoDynaLoad(msgsock, hostcommand, clinum));
		break;
	}
}

DoDynaLoad(msgsock, hostcommand, clinum)
	 int msgsock, clinum;
	 Galatea_packet *hostcommand;
{
	DynaObj *tempobj, *curobj;
	char temp[1024];
	int curext;

	tempobj = makedynaobj();
	if (tempobj == (DynaObj *)NULL) {
		if (sendint(msgsock, COULDNT_DO_FUNC) == -1) {
			return -1;
		}
		else return 0;
	}
	if ((tempobj->filename = acceptstring(msgsock)) == NULL) return -1;
	if ((tempobj->basesymbol = acceptstring(msgsock)) == NULL) {
		destroydynaobj(tempobj);
		return -1;
	}

	tempobj->objhandle = dlopen(tempobj->filename, 0666);
	if (tempobj->objhandle == (void *)NULL)  {
		destroydynaobj(tempobj);
		if (sendint(msgsock, COULDNT_DO_FUNC) == -1) {
			return -1;
		}
		else return 0;
	}
	sprintf(temp, "_%s_ext_ctrl", tempobj->basesymbol);
	tempobj->ctrlfunc = dlsym(tempobj->objhandle, temp);
	if (tempobj->ctrlfunc == (void *)NULL)  {
		destroydynaobj(tempobj);
		if (sendint(msgsock, COULDNT_DO_FUNC) == -1) {
			return -1;
		}
		else return 0;
	}
	sprintf(temp, "_%s_ext_dofuncs", tempobj->basesymbol);
	tempobj->ctrlfunc = dlsym(tempobj->objhandle, temp);
	if (tempobj->ctrlfunc == (void *)NULL)  {
		destroydynaobj(tempobj);
		if (sendint(msgsock, COULDNT_DO_FUNC) == -1) {
			return -1;
		}
		else return 0;
	}
	sprintf(temp, "_%s_ext_string", tempobj->basesymbol);
	tempobj->ctrlfunc = dlsym(tempobj->objhandle, temp);
	if (tempobj->ctrlfunc == (void *)NULL)  {
		destroydynaobj(tempobj);
		if (sendint(msgsock, COULDNT_DO_FUNC) == -1) {
			return -1;
		}
		else return 0;
	}
	curobj = topobj;
	if (curobj == (DynaObj *)NULL) {
		topobj = tempobj;
		numobjs = 1;
	}
	else {
		numobjs = 0;
		while (curobj->next != (DynaObj *)NULL) {
			curobj = curobj->next;
			numobjs++;
		}
		curobj->next = tempobj;
		numobjs++;
	}
	free(extensions);
	extensions = (ExtenList *)malloc(sizeof(ExtenList) * numobjs);
	curext = 0;
	curobj = topobj;
	while (curobj != (DynaObj *)NULL) {
		extensions[curext].the_name = curobj->stringp;
		extensions[curext].ctrlfuncs = curobj->ctrlfunc;
		extensions[curext++].dofuncs = curobj->dofunc;
	}
	need_to_rebuild_extensions = 1;
}


DynaObj *makedynaobj()
{
	DynaObj *tempobj;

	tempobj = (DynaObj *)malloc(sizeof(DynaObj));
	if (tempobj == (DynaObj *)NULL) return (DynaObj *)NULL;
	tempobj->filename = (char *)NULL;
	tempobj->basesymbol = (char *)NULL;
	tempobj->objhandle = (void *)NULL;
	tempobj->stringp = (char *)NULL;
	tempobj->ctrlfunc = (char *)NULL;
	tempobj->dofunc = (char *)NULL;
	tempobj->next = (DynaObj *)NULL;
	return (tempobj);
}

destroydynaobj(tempobj)
	 DynaObj *tempobj;
{
	if (tempobj->filename != (char *)NULL) free(tempobj->filename);
	if (tempobj->basesymbol != (char *)NULL) free(tempobj->basesymbol);
	if (tempobj->objhandle != (void *)NULL) {
		dlclose(tempobj->objhandle);
		free(tempobj->objhandle);
	}
	if (tempobj->stringp = (char *)NULL) free(tempobj->stringp);
	if (tempobj->ctrlfunc = (char *)NULL) free(tempobj->ctrlfunc);
	if (tempobj->dofunc = (char *)NULL) free(tempobj->dofunc);
	if (tempobj->next = (DynaObj *)NULL) free(tempobj->next);
	free(tempobj);
}
	
#endif /* DYNAEXT */
