#include <gsu-impl.h>
#include <gsu-lib.h>

#include <errno.h>

#ifndef max
#define max(a,b) ((a > b) ? a : b)
#endif

typedef struct {
    POA_GNOME_Su servant;
    PortableServer_POA poa;
} impl_POA_GNOME_Su;

/*** Implementation stub prototypes ***/

static void impl_GNOME_Su__destroy (impl_POA_GNOME_Su * servant,
				    CORBA_Environment * ev);

static void impl_GNOME_Su_su_command (GNOME_Su _obj, const CORBA_char * user,
				      const CORBA_char * command,
				      const GNOME_Su_arg_seq * args,
				      CORBA_Environment * ev);

/*** epv structures ***/

static PortableServer_ServantBase__epv impl_GNOME_Su_base_epv =
{
    NULL,			/* _private data */
    (gpointer) & impl_GNOME_Su__destroy,	/* finalize routine */
    NULL,			/* default_POA routine */
};

static POA_GNOME_Su__epv impl_GNOME_Su_epv =
{
    NULL,			/* _private */
    &impl_GNOME_Su_su_command,
};

/*** vepv structures ***/

static POA_GNOME_Su__vepv impl_GNOME_Su_vepv =
{
    &impl_GNOME_Su_base_epv,
    &impl_GNOME_Su_epv,
};

/*** Stub implementations ***/

GNOME_Su
impl_GNOME_Su__create (PortableServer_POA poa, CORBA_Environment * ev)
{
    GNOME_Su retval;
    impl_POA_GNOME_Su *newservant;
    PortableServer_ObjectId *objid;

    newservant = g_new0 (impl_POA_GNOME_Su, 1);
    newservant->servant.vepv = &impl_GNOME_Su_vepv;
    newservant->poa = poa;
    POA_GNOME_Su__init ((PortableServer_Servant) newservant, ev);
    objid = PortableServer_POA_activate_object (poa, newservant, ev);
    CORBA_free (objid);
    retval = PortableServer_POA_servant_to_reference (poa, newservant, ev);
    
    return retval;
}

/* You shouldn't call this routine directly without first deactivating the
 * servant... */
static void
impl_GNOME_Su__destroy (impl_POA_GNOME_Su * servant, CORBA_Environment * ev)
{
    POA_GNOME_Su__fini ((PortableServer_Servant) servant, ev);
    g_free (servant);
}

static void
impl_GNOME_Su_su_command (GNOME_Su _obj,
			  const CORBA_char * user,
			  const CORBA_char * command,
			  const GNOME_Su_arg_seq * args,
			  CORBA_Environment * ev)
{
/*	XXX FIXME: The previous code just popped up a dialog for the
	password.  I have added the called code to the end of the file
	for reference.
*/

	gsu_call_suid(command, user, password, NULL)

/*
	XXX: FIXME: It also expects a meaningful error code to be
	delivered here.  However, the as any error can be generated by
	su X, this isn't so easy.  Some of the errors can be detected
	however, have a look at gsu-gui-api.c.
*/

 no_helper:
    {
	GNOME_Su_NoSuidHelper *exception =
	    GNOME_Su_NoSuidHelper__alloc ();
	CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
			     ex_GNOME_Su_NoSuidHelper, exception);
	return;
    }

 user_abort:
    {
	GNOME_Su_UserAbort *exception =
	    GNOME_Su_UserAbort__alloc ();
	CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
			     ex_GNOME_Su_UserAbort, exception);
	return;
    }

 incorrect_password:
    {
	GNOME_Su_IncorrectPassword *exception =
	    GNOME_Su_IncorrectPassword__alloc ();
	CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
			     ex_GNOME_Su_IncorrectPassword, exception);
	return;
    }

 unknown_error:
    {
	GNOME_Su_UnknownError *exception =
	    GNOME_Su_UnknownError__alloc ();
	exception->message = CORBA_string_dup (error_message);
	CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
			     ex_GNOME_Su_UnknownError, exception);
	return;
    }
}

/* =======================================================================
 * This code has been attached because it was used by the previous
 * function to get the password.  It isn't very pretty, and I'm under
 * the impression it was temporary...
 * ======================================================================= */
gchar *
gsu_getpass (const gchar *new_user)
{
    GtkWidget *dialog;/*, *label, *entry;*/
    gchar *prompt, *password = NULL;
    gint button;
	
	if (!new_user)
		new_user = "root"; /* Default if user did not speficy one */
	
    if (strcmp (new_user, "root") == 0)
		prompt = g_strdup
			(_("You are trying to do something which requires\n"
			   "root (system administrator) privileges.\n"
			   "To do this, you must give the root password.\n"
			   "Please enter the root password now, or choose\n"
			   "Cancel if you do not know it."));
    else
		prompt = g_strdup_printf
			(_("You are trying to change your user identity.\n"
			   "Please enter the password for user `%s'."),
			 new_user);
	
    dialog = gnome_request_dialog (TRUE, prompt, NULL, 32,
		   dialog_callback, &password, NULL);
	
    g_free (prompt);
	
    button = gnome_dialog_run_and_close (GNOME_DIALOG(dialog));
	
    if (button && password) {
		g_free (password);
		password = NULL;
    }

    return password;
}
