/*dumb marshalling hack */
static void
matecomponent_activation_registration_iterate (const MateComponentActivationBaseService *base_service,
			  CORBA_Object obj, CORBA_Environment *ev,
			  gulong offset, int nargs)
{
	GSList *link;
	char *ior = NULL;

	if (nargs == 4)
		ior = CORBA_ORB_object_to_string (matecomponent_activation_orb_get (), obj, ev);

	for (link = registries; link; link = link->next) {
		RegistryInfo *ri;
		void (*func_ptr) ();

		ri = link->data;

		func_ptr = *(gpointer *) ((guchar *) ri->registry + offset);

		if (!func_ptr)
			continue;

		switch (nargs) {
		case 4:
			func_ptr (ri->registry, ior, base_service, ri->user_data);
			break;
		case 2:
			func_ptr (ri->registry, ri->user_data);
			break;
		}
	}

	if (nargs == 4)
		CORBA_free (ior);
}
CORBA_Object
matecomponent_activation_base_service_check (const MateComponentActivationBaseService *base_service,
                                      CORBA_Environment                 *ev)
{
	GSList *link;
	CORBA_Object retval = CORBA_OBJECT_NIL;
	int dist = INT_MAX;
	char *ior = NULL;

	for (link = registries; link; link = link->next) {
		RegistryInfo *ri;
		char *new_ior;
		int new_dist = dist;

		ri = link->data;

		if (!ri->registry->check)
			continue;

		new_ior = ri->registry->check (ri->registry, base_service, 
                                             &new_dist, ri->user_data);
		if (new_ior && (new_dist < dist)) {
			g_free (ior);
			ior = new_ior;
		} else if (new_ior) {
			g_free (new_ior);
		}
	}

	if (ior) {
		retval = CORBA_ORB_string_to_object (matecomponent_activation_orb_get (), ior, ev);
		if (ev->_major != CORBA_NO_EXCEPTION)
			retval = CORBA_OBJECT_NIL;

		g_free (ior);
	}

	return retval;
}
/* Copied largely from goad.c, goad_server_activate_exe() */
static CORBA_Object
od_server_activate_exe (MateComponent_ServerInfo                  *si,
			ODActivationInfo                   *actinfo,
			CORBA_Object                        od_obj,
			const MateComponent_ActivationEnvironment *environment,
			CORBA_Environment                  *ev)
{
	char **args;
	char *extra_arg, *ctmp, *ctmp2;
        int fd_arg;
	int i;
        char *iorstr, *iid;
        CORBA_Object retval;

	/* Munge the args */
	args = g_alloca (36 * sizeof (char *));
#ifndef G_OS_WIN32
        /* Split location_info into executable pathname and command-line
         * arguments.
         */
	for (i = 0, ctmp = ctmp2 = si->location_info; i < 32; i++) {
		while (*ctmp2 && !g_ascii_isspace ((guchar) *ctmp2))
			ctmp2++;
		if (!*ctmp2)
			break;

		args[i] = g_alloca (ctmp2 - ctmp + 1);
		strncpy (args[i], ctmp, ctmp2 - ctmp);
		args[i][ctmp2 - ctmp] = '\0';

		ctmp = ctmp2;
		while (*ctmp2 && g_ascii_isspace ((guchar) *ctmp2))
			ctmp2++;
		if (!*ctmp2)
			break;
		ctmp = ctmp2;
	}
	if (!g_ascii_isspace ((guchar) *ctmp) && i < 32)
		args[i++] = ctmp;
        if (i > 1)
                g_warning ("Passing command-line arguments in .server files is deprecated: \"%s\"", si->location_info);
#else
        /* We don't support command-line arguments in the location on
         * Win32, as the executable pathname might well contain spaces
         * itself (C:\Program Files\Evolution 2.6.2\libexec\...).
         * location_info is just the executable's pathname.
         */
        args[0] = g_alloca (strlen (si->location_info) + 1);
        strcpy (args[0], si->location_info);
        i = 1;
#endif

	extra_arg =
		g_alloca (strlen (si->iid) +
			    sizeof ("--oaf-activate-iid="));
	args[i++] = extra_arg;
	sprintf (extra_arg, "--oaf-activate-iid=%s", si->iid);

        fd_arg = i;
	extra_arg = g_alloca (sizeof ("--oaf-ior-fd=") + 10);
	args[i++] = "--oaf-ior-fd=%d";


        iorstr = CORBA_ORB_object_to_string (
                matecomponent_activation_orb_get (), od_obj, ev);

        if (ev->_major != CORBA_NO_EXCEPTION)
	  iorstr = NULL;

        if(actinfo->flags & MateComponent_ACTIVATION_FLAG_PRIVATE) {
                extra_arg = g_alloca (sizeof ("--oaf-private"));
                args[i++] = extra_arg;
                g_snprintf (extra_arg, sizeof ("--oaf-private"),
                            "--oaf-private");
        }

	args[i] = NULL;

        iid = g_strdup (si->iid);

        /* Here comes the too clever by 1/2 bit:
         *   we drop the (recursive) 'server_lock' - so we
         *   can get other threads re-entering / doing activations
         *   here. cf. od_server_activate_factory
         */
        {
                ServerLockState state;

                state = server_lock_drop ();
                /*
                 * We set the process group of activated servers to our process group;
                 * this allows people to destroy all OAF servers along with oafd
                 * if necessary
                 */
                retval = matecomponent_activation_server_by_forking
                        ( (const char **) args, TRUE, fd_arg, environment, iorstr,
                          iid, FALSE, matecomponent_object_directory_re_check_fn, actinfo, ev);

                server_lock_resume (state);
        }

        g_free (iid);

	CORBA_free (iorstr);

        return retval;
}
/**
 * matecomponent_activation_activate_shlib_server:
 * @sh:
 * @ev:
 *
 * Private function.
 *
 * Return value: 
 */
CORBA_Object
matecomponent_activation_activate_shlib_server (MateComponent_ActivationResult *sh, 
                                         CORBA_Environment *ev)
{
	CORBA_Object retval;
	const MateComponentActivationPlugin *plugin;
	ActivePluginInfo *local_plugin_info = NULL;
	const MateComponentActivationPluginObject *pobj;
	int i;
	PortableServer_POA poa;
	CORBA_ORB orb;
	char *filename;
	const char *iid;

	g_return_val_if_fail (sh->res._d == MateComponent_ACTIVATION_RESULT_SHLIB,
			      CORBA_OBJECT_NIL);
	g_return_val_if_fail (sh->res._u.res_shlib._length > 0,
			      CORBA_OBJECT_NIL);

        MATECOMPONENT_ACTIVATION_LOCK ();

	/* The location info is at the end to of the string list */
	filename = sh->res._u.res_shlib._buffer[sh->res._u.res_shlib._length - 1];
	if (living_by_filename)
		local_plugin_info =
			g_hash_table_lookup (living_by_filename, filename);

	if (!local_plugin_info) {
		/* We have to load the thing from scratch */
		GModule *gmod;
		gboolean success;

		gmod = g_module_open (filename, G_MODULE_BIND_LAZY);
		if (!gmod) {
                        char *error_string;
                        MateComponent_GeneralError *error = MateComponent_GeneralError__alloc ();

                        error_string = g_strdup_printf (
                                _("g_module_open of `%s' failed with `%s'"),
                                filename, g_module_error ());
                        error->description = CORBA_string_dup (error_string);
                        CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
                                             ex_MateComponent_GeneralError, error);
                        g_free (error_string);
                        MATECOMPONENT_ACTIVATION_UNLOCK ();
			return CORBA_OBJECT_NIL; /* Couldn't load it */
		}
		
		success = g_module_symbol (gmod, "MateComponent_Plugin_info",
					   (gpointer *) &plugin);
		if (!success) {
                        char *error_string;
                        MateComponent_GeneralError *error = MateComponent_GeneralError__alloc ();

			g_module_close (gmod);

                        error_string = g_strdup_printf (
                                _("Can't find symbol MateComponent_Plugin_info in `%s'"),
                                filename);
                        error->description = CORBA_string_dup (error_string);
                        CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
                                             ex_MateComponent_GeneralError, error);
                        g_free (error_string);
                        MATECOMPONENT_ACTIVATION_UNLOCK ();
			return CORBA_OBJECT_NIL;
		}

		local_plugin_info =
			g_malloc (sizeof (ActivePluginInfo) +
				  strlen (filename) + 1);

		local_plugin_info->refcount = 0;
		local_plugin_info->loaded = gmod;
		strcpy (local_plugin_info->filename, filename);

		if (!living_by_filename)
			living_by_filename =
				g_hash_table_new (g_str_hash, g_str_equal);

		g_hash_table_insert (living_by_filename,
				     local_plugin_info->filename,
				     local_plugin_info);
	} else {
		int success;

		success =
			g_module_symbol (local_plugin_info->loaded,
					 "MateComponent_Plugin_info",
					 (gpointer *) & plugin);
		if (!success) {
                        char *error_string;
                        MateComponent_GeneralError *error = MateComponent_GeneralError__alloc ();

                        error_string = g_strdup_printf (
                                _("Can't find symbol MateComponent_Plugin_info in `%s'"),
                                filename);
                        error->description = CORBA_string_dup (error_string);
                        CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
                                             ex_MateComponent_GeneralError, error);
                        g_free (error_string);
                        MATECOMPONENT_ACTIVATION_UNLOCK ();
			return CORBA_OBJECT_NIL;
		}
	}

	retval = CORBA_OBJECT_NIL;

	orb = matecomponent_activation_orb_get ();
	poa = (PortableServer_POA)
		CORBA_ORB_resolve_initial_references (orb, "RootPOA", ev);

	/* Index into the string list one element from the end to get the iid of the shlib */
	iid = sh->res._u.res_shlib._buffer[sh->res._u.res_shlib._length - 2];
	for (pobj = plugin->plugin_object_list; pobj->iid; pobj++) {
		if (strcmp (iid, pobj->iid) == 0) {
			/* Found a match */
			break;
		}
	}

	if (pobj->iid) {
		/* Activate the shlib */
		retval = pobj->activate (poa, pobj->iid, local_plugin_info, ev);

		if (ev->_major != CORBA_NO_EXCEPTION)
			retval = CORBA_OBJECT_NIL;

		/* Activate the factiories contained in the shlib */
		i =  sh->res._u.res_shlib._length - 2;
		for (i--; i >= 0 && !CORBA_Object_is_nil (retval, ev); i--) {
			CORBA_Object new_retval;

			iid = sh->res._u.res_shlib._buffer[i];

			new_retval =
				MateComponent_GenericFactory_createObject (
                                        retval, (char *) iid, ev);

			if (ev->_major != CORBA_NO_EXCEPTION
			    || CORBA_Object_is_nil (new_retval, ev)) {
                                if (ev->_major == CORBA_NO_EXCEPTION) {
                                        MateComponent_GeneralError *error = MateComponent_GeneralError__alloc ();
                                        char *error_string = g_strdup_printf (
                                                _("Factory `%s' returned NIL for `%s'"),
                                                pobj->iid, iid);
                                        error->description = CORBA_string_dup (error_string);
                                        CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
                                                             ex_MateComponent_GeneralError, error);
                                        g_free (error_string);
                                        
                                }
				new_retval = CORBA_OBJECT_NIL;
                        }

			CORBA_Object_release (retval, ev);
			retval = new_retval;
		}
	} else {
                MateComponent_GeneralError *error = MateComponent_GeneralError__alloc ();
                char *error_string = g_strdup_printf (
                        _("Shlib `%s' didn't contain `%s'"),
                        filename, iid);
                error->description = CORBA_string_dup (error_string);
                CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
                                     ex_MateComponent_GeneralError, error);
                g_free (error_string);
        }

        CORBA_Object_release ((CORBA_Object) poa, ev);
        MATECOMPONENT_ACTIVATION_UNLOCK ();

	return retval;
}