[gdm-list] PoC for multiple pam prompts
- From: Ludwig Nussel <ludwig nussel suse de>
- To: gdm-list gnome org
- Subject: [gdm-list] PoC for multiple pam prompts
- Date: Thu, 1 Feb 2007 16:38:02 +0100
Hi,
I've started to implement multiple pam prompts in gdmlogin. It looks
like this[1]:
http://www.suse.de/~lnussel/gdm/gdm1.png
http://www.suse.de/~lnussel/gdm/gdm2.png
The patch works but is not ready for production yet. gdmgreeter not
supported yet. I post it here for discussion and for the brave for
testing.
Something I am undecided about are convenience messages to the user
that are not originating from a pam conversation (like
authentication failed). verify-pam currently uses GDM_MSG and
GDM_ERRBOX for that. IMO there should be some dedicated way to show
such messages. I've added a status bar for the 'please enter your
username' message to see how that looks. Maybe a tooltip like popup
would be suitable for that as well.
cu
Ludwig
[1] might take a while until the web server actually mirrors it
--
(o_ Ludwig Nussel
//\ SUSE LINUX Products GmbH, Development
V_/_ http://www.suse.de/
Index: gdm2/daemon/gdm.h
===================================================================
--- gdm2.orig/daemon/gdm.h
+++ gdm2/daemon/gdm.h
@@ -31,6 +31,7 @@
* leaves MAX_PASS undefined. */
#define STX 0x2 /* Start of txt */
+#define EOX 0x3 /* End of txt */
#define BEL 0x7 /* Bell, used to interrupt login for
* say timed login or something similar */
@@ -91,8 +92,9 @@ enum {
/* This will change if there are incompatible
* protocol changes */
-#define GDM_GREETER_PROTOCOL_VERSION "3"
+#define GDM_GREETER_PROTOCOL_VERSION "4"
+#define GDM_PAM_FORM 'p'
#define GDM_MSG 'D'
#define GDM_NOECHO 'U'
#define GDM_PROMPT 'N'
Index: gdm2/daemon/slave.c
===================================================================
--- gdm2.orig/daemon/slave.c
+++ gdm2/daemon/slave.c
@@ -1995,10 +1995,12 @@ gdm_slave_wait_for_login (void)
g_free (login);
login = NULL;
/* clear any error */
+#if 0
gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, "");
gdm_slave_greeter_ctl_no_ret
(GDM_MSG,
_("You must authenticate as root to run configuration."));
+#endif
/* we always allow root for this */
oldAllowRoot = gdm_get_value_bool (GDM_KEY_ALLOW_ROOT);
@@ -2018,8 +2020,10 @@ gdm_slave_wait_for_login (void)
d->attached);
gdm_set_value_bool (GDM_KEY_ALLOW_ROOT, oldAllowRoot);
+#if 0
/* Clear message */
gdm_slave_greeter_ctl_no_ret (GDM_MSG, "");
+#endif
if G_UNLIKELY (do_restart_greeter) {
g_free (login);
Index: gdm2/daemon/verify-pam.c
===================================================================
--- gdm2.orig/daemon/verify-pam.c
+++ gdm2/daemon/verify-pam.c
@@ -468,6 +468,18 @@ perhaps_translate_message (const char *m
/* Internal PAM conversation function. Interfaces between the PAM
* authentication system and the actual greeter program */
+static inline char msg_style2gdm(int msg_style)
+{
+ switch (msg_style) {
+ case PAM_PROMPT_ECHO_ON: return GDM_PROMPT;
+ case PAM_PROMPT_ECHO_OFF: return GDM_NOECHO;
+ case PAM_ERROR_MSG: return GDM_ERRBOX;
+ case PAM_TEXT_INFO: return GDM_MSG;
+ }
+ gdm_assert_not_reached();
+ return 0;
+}
+
static int
gdm_verify_pam_conv (int num_msg, const struct pam_message **msg,
struct pam_response **resp,
@@ -476,10 +488,15 @@ gdm_verify_pam_conv (int num_msg, const
int replies = 0;
int i;
char *s = NULL;
+ char* str = NULL;
+ size_t sendbuflen = 0;
struct pam_response *reply = NULL;
const void *p;
const char *login;
+ if(!num_msg) /* weird */
+ return PAM_SUCCESS;
+
if (pamh == NULL)
return PAM_CONV_ERR;
@@ -491,18 +508,12 @@ gdm_verify_pam_conv (int num_msg, const
if ( ! gdm_slave_action_pending () || selected_user)
return PAM_CONV_ERR;
- reply = malloc (sizeof (struct pam_response) * num_msg);
-
- if (reply == NULL)
- return PAM_CONV_ERR;
-
- memset (reply, 0, sizeof (struct pam_response) * num_msg);
-
/* Here we set the login if it wasn't already set,
* this is kind of anal, but this way we guarantee that
* the greeter always is up to date on the login */
if (pam_get_item (pamh, PAM_USER, &p) == PAM_SUCCESS) {
- login = (const char *)p;
+ login = (const char *)p;
+ if(login)
gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login);
}
@@ -510,88 +521,105 @@ gdm_verify_pam_conv (int num_msg, const
closelog ();
openlog ("gdm", LOG_PID, LOG_DAEMON);
+ if (gdm_slave_greeter_check_interruption ())
+ return PAM_CONV_ERR;
+
+ /* check for valid form first */
+ if(num_msg > 255-'\n') {
+ gdm_error("too many prompts");
+ return PAM_CONV_ERR;
+ }
+ sendbuflen = 1 /* num_msg */;
+ for (replies = 0; replies < num_msg; replies++) {
+ switch ((*msg)[replies].msg_style) {
+ case PAM_PROMPT_ECHO_OFF:
+ case PAM_PROMPT_ECHO_ON:
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ {
+ const char *m = (*msg)[replies].msg;
+ size_t len;
+ m = perhaps_translate_message (m);
+ len = strlen(m);
+ if(len > 255-'\n') {
+ gdm_error("pam prompt too long");
+ return PAM_CONV_ERR;
+ }
+ if (!len) len = 1;
+ sendbuflen += 1 /* type */ + len + 1 /* \0 */;
+ }
+ break;
+ default:
+ return PAM_CONV_ERR;
+ }
+ }
+
+ s = str = malloc(sendbuflen);
+
+ /* prevent low values from beeing interpreted as control chars */
+ *s++ = num_msg + '\n';
+
for (replies = 0; replies < num_msg; replies++) {
+
const char *m = (*msg)[replies].msg;
m = perhaps_translate_message (m);
+ m = ve_sure_string(m);
- switch ((*msg)[replies].msg_style) {
-
- /* PAM requested textual input with echo on */
- case PAM_PROMPT_ECHO_ON:
- if (strcmp (m, _("Username:")) == 0) {
- if ( ve_string_empty (selected_user)) {
- /* this is an evil hack, but really there is no way we'll
- know this is a username prompt. However we SHOULD NOT
- rely on this working. The pam modules can set their
- prompt to whatever they wish to */
- gdm_slave_greeter_ctl_no_ret
- (GDM_MSG, _("Please enter your username"));
- s = gdm_slave_greeter_ctl (GDM_PROMPT, m);
- /* this will clear the message */
- gdm_slave_greeter_ctl_no_ret (GDM_MSG, "");
- }
- } else {
- s = gdm_slave_greeter_ctl (GDM_PROMPT, m);
- }
+ *s++ = msg_style2gdm((*msg)[replies].msg_style);
+ strcpy(s, m);
+ // XXX: remove EOX from string
+ s[strlen(m)] = EOX;
+ s += strlen(m)+1;
+ }
- if (gdm_slave_greeter_check_interruption ()) {
- g_free (s);
- for (i = 0; i < replies; i++)
- if (reply[replies].resp != NULL)
- free (reply[replies].resp);
- free (reply);
- return PAM_CONV_ERR;
- }
+ s = gdm_slave_greeter_ctl(GDM_PAM_FORM, str);
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = strdup (ve_sure_string (s));
- g_free (s);
- break;
-
- case PAM_PROMPT_ECHO_OFF:
- if (strcmp (m, _("Password:")) == 0)
- did_we_ask_for_password = TRUE;
- /* PAM requested textual input with echo off */
- s = gdm_slave_greeter_ctl (GDM_NOECHO, m);
- if (gdm_slave_greeter_check_interruption ()) {
- g_free (s);
- for (i = 0; i < replies; i++)
- if (reply[replies].resp != NULL)
- free (reply[replies].resp);
- free (reply);
- return PAM_CONV_ERR;
- }
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = strdup (ve_sure_string (s));
- g_free (s);
- break;
-
- case PAM_ERROR_MSG:
- /* PAM sent a message that should displayed to the user */
- gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, m);
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = NULL;
- break;
- case PAM_TEXT_INFO:
- /* PAM sent a message that should displayed to the user */
- gdm_slave_greeter_ctl_no_ret (GDM_MSG, m);
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies].resp = NULL;
- break;
-
- default:
- /* PAM has been smoking serious crack */
- for (i = 0; i < replies; i++)
- if (reply[replies].resp != NULL)
- free (reply[replies].resp);
- free (reply);
- return PAM_CONV_ERR;
+ if (gdm_slave_greeter_check_interruption ())
+ goto error;
+
+ if(!s || s[0] == '\n')
+ {
+ g_free(s);
+ gdm_error("empty reply from greeter");
+ goto error;
+ }
+
+ free(str);
+ str = s;
+
+ reply = malloc (sizeof (struct pam_response) * num_msg);
+
+ if (reply == NULL)
+ return PAM_CONV_ERR;
+
+ memset (reply, 0, sizeof (struct pam_response) * num_msg);
+
+ for (replies = 0; replies < num_msg; ++replies) {
+ char* eos = strchr(s, EOX);
+ if(!eos || !s[0] || s[0] == '\n') {
+ gdm_error("invalid reply from greeter");
+ goto error;
}
-
+ *eos = '\0';
+ gdm_info("%d %s", replies, s);
+ reply[replies].resp = strdup(s);
+ reply[replies].resp_retcode = PAM_SUCCESS;
+ s = eos + 1;
}
*resp = reply;
return PAM_SUCCESS;
+
+error:
+ if(reply)
+ for (i = 0; i < replies; ++i)
+ if (reply[replies].resp != NULL)
+ free (reply[replies].resp);
+
+ free (reply);
+ free(str);
+
+ return PAM_CONV_ERR;
}
@@ -1133,7 +1161,7 @@ authenticate_again:
} else {
msg = g_strdup (basemsg);
}
- gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, msg);
+ gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, msg);
g_free (msg);
} else {
gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, _("Authentication failed"));
Index: gdm2/gui/gdmlogin.c
===================================================================
--- gdm2.orig/gui/gdmlogin.c
+++ gdm2/gui/gdmlogin.c
@@ -95,21 +95,18 @@ static GtkWidget *logo_frame = NULL;
static GtkWidget *logo_image = NULL;
static GtkWidget *table = NULL;
static GtkWidget *welcome;
-static GtkWidget *label;
static GtkWidget *icon_button = NULL;
static GtkWidget *title_box = NULL;
static GtkWidget *clock_label = NULL;
-static GtkWidget *entry;
+static GtkWidget *gui_form_vbox;
static GtkWidget *ok_button;
static GtkWidget *start_again_button;
-static GtkWidget *msg;
static GtkWidget *auto_timed_msg;
-static GtkWidget *err_box;
-static guint err_box_clear_handler = 0;
static gboolean require_quarter = FALSE;
static GtkWidget *icon_win = NULL;
static GtkWidget *sessmenu;
static GtkWidget *langmenu;
+static GtkWidget *statusbar;
static gboolean login_is_local = FALSE;
@@ -148,6 +145,14 @@ static gboolean back_prog_delayed = FALS
static guint timed_handler_id = 0;
+static struct {
+ unsigned style;
+ const char* msg;
+ GtkWidget* widget;
+} pam_form[256-'\n'] = {{0, NULL, NULL}}; /* can't have more than that anyways */
+static unsigned num_pam_form = 0;
+GtkWidget* pam_form_vbox = NULL;
+
#if FIXME
static char *selected_browser_user = NULL;
#endif
@@ -176,8 +181,18 @@ static void back_prog_launch_after_timeo
static void back_prog_run (void);
static void back_prog_stop (void);
+static void gui_process_form(void);
static void process_operation (guchar op_code, const gchar *args);
+static gboolean pop_statusbar (gpointer data);
+static void update_statusbar_timeout (const char* text);
+static void update_statusbar (const char* text);
+static guint statusbar_timeout_id;
+
+
+static gboolean username_prompt_focus_in(GtkWidget *widget, GdkEventFocus *event);
+static gboolean username_prompt_focus_out (GtkWidget *widget, GdkEventFocus *event);
+
/*
* This function is called when the background program exits.
* It will add a timer to restart the program after the
@@ -519,6 +534,7 @@ gdm_event (GSignalInvocationHint *ihint,
&& event->button.button == 3)
event->button.button = 1;
+#if 0
/* Support Ctrl-U for blanking the username/password entry */
if (event->type == GDK_KEY_PRESS &&
(event->key.state & GDK_CONTROL_MASK) &&
@@ -527,6 +543,7 @@ gdm_event (GSignalInvocationHint *ihint,
gtk_entry_set_text (GTK_ENTRY (entry), "");
}
+#endif
return TRUE;
}
@@ -835,6 +852,7 @@ dance (gpointer data)
return TRUE;
}
+#if 0
static gboolean
evil (const char *user)
{
@@ -878,7 +896,9 @@ evil (const char *user)
return FALSE;
}
+#endif
+#if 0
static void
gdm_login_enter (GtkWidget *entry)
{
@@ -934,16 +954,45 @@ gdm_login_enter (GtkWidget *entry)
fflush (stdout);
g_free (tmp);
}
+#endif
static void
gdm_login_ok_button_press (GtkButton *button, GtkWidget *entry)
{
- gdm_login_enter (entry);
+ unsigned i;
+
+ gdm_common_info("%d form items", num_pam_form);
+ fputc(STX, stdout);
+ for(i = 0; i < num_pam_form; ++i) {
+ char* s = NULL;
+ switch(pam_form[i].style) {
+ case GDM_NOECHO:
+ case GDM_PROMPT:
+ s = ve_locale_from_utf8(gtk_entry_get_text(GTK_ENTRY(pam_form[i].widget)));
+ }
+ if(pam_form[i].widget)
+ gtk_widget_set_sensitive(GTK_WIDGET(pam_form[i].widget), FALSE);
+ gdm_common_info("-> %d %d %s", i, pam_form[i].style, s);
+ fputs(ve_sure_string(s), stdout);
+ fputc(EOX, stdout);
+ g_free(s);
+ }
+ fputc('\n', stdout);
+ fflush (stdout);
+
+#if 0
+ /* don't do that to prevent resizes */
+ gtk_container_remove(GTK_CONTAINER(gui_form_vbox), pam_form_vbox);
+ pam_form_vbox = NULL;
+#endif
+
+ gdm_common_info("OK!");
}
static void
-gdm_login_start_again_button_press (GtkButton *button, GtkWidget *entry)
+gdm_login_start_again_button_press (GtkButton *button, gpointer data)
{
+ unsigned i;
GtkTreeSelection *selection;
if (browser != NULL) {
@@ -955,6 +1004,18 @@ gdm_login_start_again_button_press (GtkB
g_free (selected_user);
selected_user = NULL;
+ for(i = 0; i < num_pam_form; ++i) {
+ if(pam_form[i].widget)
+ gtk_widget_set_sensitive(GTK_WIDGET(pam_form[i].widget), FALSE);
+ }
+#if 0
+ /* don't do that to prevent resizes */
+ gtk_container_remove(GTK_CONTAINER(gui_form_vbox), pam_form_vbox);
+ pam_form_vbox = NULL;
+#endif
+
+ gtk_widget_set_sensitive (ok_button, FALSE);
+
printf ("%c%c%c\n", STX, BEL,
GDM_INTERRUPT_CANCEL);
fflush (stdout);
@@ -981,6 +1042,57 @@ gdm_login_focus_out (GtkWidget *widget,
return FALSE;
}
+static gboolean
+username_prompt_focus_in(GtkWidget *widget, GdkEventFocus *event)
+{
+ update_statusbar(_("Please enter your username"));
+ return FALSE;
+}
+
+static gboolean
+username_prompt_focus_out (GtkWidget *widget, GdkEventFocus *event)
+{
+ update_statusbar(NULL);
+ return FALSE;
+}
+
+static gboolean
+pop_statusbar(gpointer data)
+{
+ guint id = GPOINTER_TO_INT(data);
+ gtk_statusbar_pop(GTK_STATUSBAR(statusbar), id);
+ return TRUE;
+}
+
+static void update_statusbar_timeout (const char* text)
+{
+ guint id = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "timeout");
+
+ gtk_statusbar_pop(GTK_STATUSBAR(statusbar), id);
+
+ if(!text)
+ return;
+
+ gtk_statusbar_push(GTK_STATUSBAR(statusbar), id, text);
+
+ if(statusbar_timeout_id)
+ g_source_remove (statusbar_timeout_id);
+
+ statusbar_timeout_id = g_timeout_add (5000, pop_statusbar, GINT_TO_POINTER(id));
+}
+
+static void update_statusbar(const char* text)
+{
+ guint id = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "static");
+
+ gtk_statusbar_pop(GTK_STATUSBAR(statusbar), id);
+
+ if(!text)
+ return;
+
+ gtk_statusbar_push(GTK_STATUSBAR(statusbar), id, text);
+}
+
static void
gdm_login_session_handler (GtkWidget *widget)
{
@@ -990,7 +1102,8 @@ gdm_login_session_handler (GtkWidget *wi
s = g_strdup_printf (_("%s session selected"), gdm_session_name (current_session));
- gtk_label_set_text (GTK_LABEL (msg), s);
+ update_statusbar_timeout(s);
+
g_free (s);
login_window_resize (FALSE /* force */);
@@ -1094,7 +1207,7 @@ gdm_login_language_handler (GtkWidget *w
TRUE /* makrup */);
s = g_strdup_printf (_("%s language selected"), name);
g_free (name);
- gtk_label_set_markup (GTK_LABEL (msg), s);
+ update_statusbar_timeout(s);
g_free (s);
login_window_resize (FALSE /* force */);
@@ -1372,6 +1485,7 @@ gdm_login_theme_menu_new (void)
return menu;
}
+#if 0
static gboolean
err_box_clear (gpointer data)
{
@@ -1381,6 +1495,7 @@ err_box_clear (gpointer data)
err_box_clear_handler = 0;
return FALSE;
}
+#endif
static void
browser_set_user (const char *user)
@@ -1390,6 +1505,8 @@ browser_set_user (const char *user)
GtkTreeIter iter = {0};
GtkTreeModel *tm = NULL;
+ gdm_common_info("%s %s", __FUNCTION__, user);
+
if (browser == NULL)
return;
@@ -1522,6 +1639,142 @@ gdm_login_ctrl_handler (GIOChannel *sour
return TRUE;
}
+static void gui_process_form(void)
+{
+ int i;
+ int firstentry = -1;
+ GtkWidget* preventry = NULL;
+
+ gdm_common_info("%s", __FUNCTION__);
+
+ if(pam_form_vbox)
+ gtk_container_remove(GTK_CONTAINER(gui_form_vbox), pam_form_vbox);
+
+ pam_form_vbox = gtk_vbox_new(FALSE, 0);
+
+ for (i = 0; i < num_pam_form; ++i)
+ {
+ unsigned style = pam_form[i].style;
+ char* msg = ve_locale_from_utf8(pam_form[i].msg);
+
+ gdm_common_info("%c %s", style, msg);
+
+ switch(style)
+ {
+ case GDM_NOECHO:
+ case GDM_PROMPT:
+ {
+ GtkWidget* hbox;
+ GtkWidget* label;
+ GtkWidget* entry;
+ gboolean is_username;
+
+ if((is_username = !strcmp(msg, _("Username:"))))
+ msg = _("_Username:");
+
+ hbox = gtk_hbox_new(FALSE, 4);
+ label = gtk_label_new_with_mnemonic(msg);
+ pam_form[i].widget = entry = gtk_entry_new();
+ gtk_widget_set_size_request (entry, 200, -1);
+
+ if(style == GDM_NOECHO)
+ {
+ gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
+ }
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+
+ gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, TRUE, 0);
+
+ gtk_box_pack_start(GTK_BOX(pam_form_vbox), hbox, TRUE, TRUE, 0);
+
+ if(firstentry == -1)
+ firstentry = i;
+
+ if(is_username)
+ {
+ msg = NULL; // static string from gettext, prevent g_free()
+
+ if(selected_user)
+ gtk_entry_set_text (GTK_ENTRY(entry), selected_user);
+
+ /* TODO: set callback for evil() */
+
+ g_signal_connect (G_OBJECT (entry), "focus_in_event",
+ G_CALLBACK (username_prompt_focus_in),
+ NULL);
+ g_signal_connect (G_OBJECT (entry), "focus_out_event",
+ G_CALLBACK (username_prompt_focus_out),
+ NULL);
+ }
+
+ if(preventry)
+ {
+ g_signal_connect_swapped((gpointer)preventry, "activate",
+ G_CALLBACK(gtk_widget_grab_focus),
+ entry);
+ }
+
+ preventry = entry;
+
+ } break;
+ case GDM_MSG:
+ case GDM_ERRBOX:
+ {
+ GtkWidget* hbox;
+ GtkWidget* label;
+ GtkWidget* icon;
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ label = gtk_label_new(msg);
+
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+
+ if(style == GDM_ERRBOX)
+ icon = gtk_image_new_from_stock(
+ GTK_STOCK_DIALOG_ERROR,
+ GTK_ICON_SIZE_BUTTON);
+ else
+ icon = gtk_image_new_from_stock(
+ GTK_STOCK_DIALOG_INFO,
+ GTK_ICON_SIZE_BUTTON);
+
+ gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(pam_form_vbox), hbox, TRUE, TRUE, 2);
+
+ } break;
+ }
+
+ g_free(msg);
+ }
+
+ gtk_widget_show_all(pam_form_vbox);
+
+ gtk_box_pack_start(GTK_BOX(gui_form_vbox), pam_form_vbox, TRUE, TRUE, 0);
+ gtk_box_reorder_child(GTK_BOX(gui_form_vbox), pam_form_vbox, 1);
+
+ if(firstentry != -1)
+ {
+ gtk_window_set_focus (GTK_WINDOW (login), pam_form[firstentry].widget);
+ }
+
+ // enter in last entry behaves like klicking the ok button
+ if(preventry)
+ {
+ g_signal_connect_swapped((gpointer)preventry, "activate",
+ G_CALLBACK (gtk_button_clicked),
+ ok_button);
+ }
+
+ gtk_widget_set_sensitive (start_again_button, TRUE);
+ gtk_widget_set_sensitive (ok_button, TRUE);
+
+ login_window_resize(FALSE);
+}
+
static void
process_operation (guchar op_code,
const gchar *args)
@@ -1529,13 +1782,12 @@ process_operation (guchar op_code,
char *tmp;
gint i, x, y;
GtkWidget *dlg;
- static gboolean replace_msg = TRUE;
- static gboolean messages_to_give = FALSE;
- gboolean greeter_probably_login_prompt = FALSE;
gint lookup_status = SESSION_LOOKUP_SUCCESS;
gchar *firstmsg = NULL;
gchar *secondmsg = NULL;
gint save_session = GTK_RESPONSE_NO;
+
+ gdm_common_info("code %c", op_code);
/* Parse opcode */
switch (op_code) {
@@ -1549,7 +1801,64 @@ process_operation (guchar op_code,
printf ("%c\n", STX);
fflush (stdout);
break;
+
+ case GDM_PAM_FORM:
+ {
+ unsigned num_msg = *args++;
+ unsigned i = 0;
+ num_msg -= '\n';
+
+ memset(pam_form, 0, sizeof(pam_form));
+
+ while(i < num_msg)
+ {
+ unsigned style = *args++;
+ char* s = strchr(args, EOX);
+ if(!s) {
+ printf ("%c\n", STX);
+ fflush (stdout);
+ gdm_common_fail_greeter("invalid message in GDM_PAM_FORM");
+ return;
+ }
+ *s = '\0';
+ // TODO: ve_locale_to_utf8
+ switch(style) {
+ case GDM_PROMPT:
+ case GDM_NOECHO:
+ case GDM_ERRBOX:
+ case GDM_MSG:
+ break;
+
+ default:
+ printf ("%c\n", STX);
+ fflush (stdout);
+ gdm_common_fail_greeter("Unexpected message type in GDM_PAM_FORM: 0x%hhx", style);
+ return;
+ }
+ pam_form[i].style = style;
+ pam_form[i].msg = args;
+ args += strlen(args)+1;
+ ++i;
+ }
+ num_pam_form = num_msg;
+ gui_process_form();
+ break;
+ }
+ case GDM_ERRBOX:
+ case GDM_MSG:
+ // TODO: check whether a form is already active and switch
+ // to dialog if so
+ case GDM_PROMPT:
+ case GDM_NOECHO:
+ memset(pam_form, 0, sizeof(pam_form));
+ pam_form[0].style = op_code;
+ pam_form[0].msg = args;
+ num_pam_form = 1;
+ gui_process_form();
+ break;
+
+#if 0
case GDM_PROMPT:
tmp = ve_locale_to_utf8 (args);
if (tmp != NULL && strcmp (tmp, _("Username:")) == 0) {
@@ -1677,6 +1986,7 @@ process_operation (guchar op_code,
login_window_resize (FALSE /* force */);
break;
+#endif
case GDM_ERRDLG:
/* we should be now fine for focusing new windows */
@@ -1822,17 +2132,31 @@ process_operation (guchar op_code,
curuser = NULL;
}
- gtk_widget_set_sensitive (entry, TRUE);
gtk_widget_set_sensitive (ok_button, FALSE);
gtk_widget_set_sensitive (start_again_button, FALSE);
+ gtk_container_remove(GTK_CONTAINER(gui_form_vbox), pam_form_vbox);
+ pam_form_vbox = NULL;
+ num_pam_form = 0;
+
if (browser_ok && gdm_config_get_bool (GDM_KEY_BROWSER))
gtk_widget_set_sensitive (GTK_WIDGET (browser), TRUE);
- tmp = ve_locale_to_utf8 (args);
- gtk_label_set_text (GTK_LABEL (msg), tmp);
- g_free (tmp);
- gtk_widget_show (GTK_WIDGET (msg));
+ if(!ve_string_empty(args)) {
+ tmp = ve_locale_to_utf8 (args);
+ dlg = ve_hig_dialog_new (NULL /* parent */,
+ GTK_DIALOG_MODAL /* flags */,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "%s", tmp);
+ gdm_wm_center_window (GTK_WINDOW (dlg));
+
+ gdm_wm_no_login_focus_push ();
+ gtk_dialog_run (GTK_DIALOG (dlg));
+ gtk_widget_destroy (dlg);
+ gdm_wm_no_login_focus_pop ();
+ g_free (tmp);
+ }
printf ("%c\n", STX);
fflush (stdout);
@@ -1870,31 +2194,6 @@ process_operation (guchar op_code,
/* Hide the login window now */
gtk_widget_hide (login);
- if (messages_to_give) {
- const char *oldtext;
- oldtext = gtk_label_get_text (GTK_LABEL (msg));
-
- if ( ! ve_string_empty (oldtext)) {
- /* we should be now fine for focusing new windows */
- gdm_wm_focus_new_windows (TRUE);
-
- dlg = ve_hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_OK,
- oldtext,
- "");
- gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
- gdm_wm_center_window (GTK_WINDOW (dlg));
-
- gdm_wm_no_login_focus_push ();
- gtk_dialog_run (GTK_DIALOG (dlg));
- gtk_widget_destroy (dlg);
- gdm_wm_no_login_focus_pop ();
- }
- messages_to_give = FALSE;
- }
-
gdm_kill_thingies ();
gdk_flush ();
@@ -2055,14 +2354,6 @@ user_selected (GtkTreeSelection *selecti
gtk_tree_model_get (tm, &iter, GREETER_ULIST_LOGIN_COLUMN,
&login, -1);
if (login != NULL) {
- const char *str = gtk_label_get_text (GTK_LABEL (label));
-
- if (selecting_user &&
- str != NULL &&
- (strcmp (str, _("Username:")) == 0 ||
- strcmp (str, _("_Username:")) == 0)) {
- gtk_entry_set_text (GTK_ENTRY (entry), login);
- }
#ifdef FIXME
selected_browser_user = g_strdup (login);
#endif
@@ -2076,12 +2367,6 @@ user_selected (GtkTreeSelection *selecti
}
}
-static void
-browser_change_focus (GtkWidget *widget, GdkEventButton *event, gpointer data)
-{
- gtk_widget_grab_focus (entry);
-}
-
static gboolean
gdm_login_handle_pressed (GtkWidget *widget, GdkEventButton *event)
{
@@ -2302,6 +2587,7 @@ window_browser_event (GtkWidget *window,
return FALSE;
}
+#if 0
static gboolean
key_release_event (GtkWidget *entry, GdkEventKey *event, gpointer data)
{
@@ -2314,6 +2600,7 @@ key_release_event (GtkWidget *entry, Gdk
return TRUE;
}
+#if 0 // don't try to be smart. maybe it's an optional entry field
/*
* Set ok button to sensitive only if there are characters in
* the entry field
@@ -2323,9 +2610,11 @@ key_release_event (GtkWidget *entry, Gdk
gtk_widget_set_sensitive (ok_button, TRUE);
else
gtk_widget_set_sensitive (ok_button, FALSE);
+#endif
return FALSE;
}
+#endif
static void
gdm_set_welcomemsg (void)
@@ -2349,7 +2638,7 @@ gdm_login_gui_init (void)
GtkTreeSelection *selection;
GtkWidget *frame1, *frame2, *ebox;
GtkWidget *mbox, *menu, *menubar, *item;
- GtkWidget *stack, *hline1, *hline2, *handle;
+ GtkWidget *handle;
GtkWidget *bbox = NULL;
GtkWidget /**help_button,*/ *button_box;
gint rows, i;
@@ -2590,10 +2879,6 @@ gdm_login_gui_init (void)
G_CALLBACK (user_selected),
NULL);
- g_signal_connect (browser, "button_release_event",
- G_CALLBACK (browser_change_focus),
- NULL);
-
gtk_tree_view_set_model (GTK_TREE_VIEW (browser), browser_model);
column = gtk_tree_view_column_new_with_attributes
(_("Icon"),
@@ -2668,11 +2953,18 @@ gdm_login_gui_init (void)
gtk_widget_set_size_request (logo_image, lw, lh);
gtk_widget_show (GTK_WIDGET (logo_image));
+#if 0
stack = gtk_table_new (7, 1, FALSE);
gtk_widget_ref (stack);
g_object_set_data_full (G_OBJECT (login), "stack", stack,
(GDestroyNotify) gtk_widget_unref);
gtk_widget_show (stack);
+#endif
+
+ gui_form_vbox = gtk_vbox_new(FALSE, 0);
+ g_object_set_data_full (G_OBJECT (login), "gui_form_vbox", gui_form_vbox,
+ (GDestroyNotify) gtk_widget_unref);
+ gtk_widget_show (gui_form_vbox);
/* Welcome msg */
welcome = gtk_label_new (NULL);
@@ -2682,10 +2974,15 @@ gdm_login_gui_init (void)
g_object_set_data_full (G_OBJECT (login), "welcome", welcome,
(GDestroyNotify) gtk_widget_unref);
gtk_widget_show (welcome);
+#if 0
gtk_table_attach (GTK_TABLE (stack), welcome, 0, 1, 0, 1,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 15);
+#endif
+ gtk_box_pack_start(GTK_BOX(gui_form_vbox), welcome, TRUE, TRUE, 0);
+
+#if 0
/* Put in error box here */
err_box = gtk_label_new (NULL);
gtk_widget_set_name (err_box, "Error box");
@@ -2776,14 +3073,18 @@ gdm_login_gui_init (void)
g_object_set_data_full (G_OBJECT (login), "msg", msg,
(GDestroyNotify) gtk_widget_unref);
gtk_widget_show (msg);
+#endif
auto_timed_msg = gtk_label_new ("");
gtk_widget_set_name (auto_timed_msg, "Message");
gtk_label_set_line_wrap (GTK_LABEL (auto_timed_msg), TRUE);
gtk_label_set_justify (GTK_LABEL (auto_timed_msg), GTK_JUSTIFY_LEFT);
+#if 0
gtk_table_attach (GTK_TABLE (stack), auto_timed_msg, 0, 1, 7, 8,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (GTK_FILL), 0, 10);
+#endif
+ gtk_box_pack_start(GTK_BOX(gui_form_vbox), auto_timed_msg, TRUE, TRUE, 0);
gtk_widget_set_size_request (auto_timed_msg, -1, 15);
gtk_widget_ref (auto_timed_msg);
@@ -2798,14 +3099,14 @@ gdm_login_gui_init (void)
GTK_WIDGET_UNSET_FLAGS (ok_button, GTK_CAN_FOCUS);
g_signal_connect (G_OBJECT (ok_button), "clicked",
G_CALLBACK (gdm_login_ok_button_press),
- entry);
+ NULL);
gtk_widget_show (ok_button);
start_again_button = gtk_button_new_with_mnemonic (_("_Start Again"));
GTK_WIDGET_UNSET_FLAGS (start_again_button, GTK_CAN_FOCUS);
g_signal_connect (G_OBJECT (start_again_button), "clicked",
G_CALLBACK (gdm_login_start_again_button_press),
- entry);
+ /* entry */ NULL);
gtk_widget_show (start_again_button);
button_box = gtk_hbutton_box_new ();
@@ -2825,9 +3126,12 @@ gdm_login_gui_init (void)
FALSE, TRUE, 0);
gtk_widget_show (button_box);
+#if 0
gtk_table_attach (GTK_TABLE (stack), button_box, 0, 1, 8, 9,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (GTK_FILL), 10, 10);
+#endif
+ gtk_box_pack_start(GTK_BOX(gui_form_vbox), button_box, TRUE, TRUE, 0);
/* Put it nicely together */
@@ -2838,20 +3142,22 @@ gdm_login_gui_init (void)
gtk_table_attach (GTK_TABLE (table), logo_frame, 0, 1, 1, 2,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (GTK_FILL), 0, 0);
- gtk_table_attach (GTK_TABLE (table), stack, 1, 2, 1, 2,
+ gtk_table_attach (GTK_TABLE (table), gui_form_vbox, 1, 2, 1, 2,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (GTK_FILL), 0, 0);
} else {
gtk_table_attach (GTK_TABLE (table), logo_frame, 0, 1, 0, 1,
(GtkAttachOptions) (0),
(GtkAttachOptions) (GTK_FILL), 0, 0);
- gtk_table_attach (GTK_TABLE (table), stack, 1, 2, 0, 1,
+ gtk_table_attach (GTK_TABLE (table), gui_form_vbox, 1, 2, 0, 1,
(GtkAttachOptions) (0),
(GtkAttachOptions) (GTK_FILL), 0, 0);
}
+
+ statusbar = gtk_statusbar_new();
+ gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusbar), FALSE);
+ gtk_box_pack_start (GTK_BOX (mbox), statusbar, TRUE, TRUE, 0);
- gtk_widget_grab_focus (entry);
- gtk_window_set_focus (GTK_WINDOW (login), entry);
g_object_set (G_OBJECT (login),
"allow_grow", TRUE,
"allow_shrink", TRUE,
@@ -2872,11 +3178,8 @@ gdm_login_gui_init (void)
G_CALLBACK (gdm_login_focus_out),
NULL);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
-
/* normally disable the prompt first */
if ( ! DOING_GDM_DEVELOPMENT) {
- gtk_widget_set_sensitive (entry, FALSE);
gtk_widget_set_sensitive (ok_button, FALSE);
gtk_widget_set_sensitive (start_again_button, FALSE);
}
@@ -3401,6 +3704,9 @@ main (int argc, char *argv[])
gtk_init (&argc, &argv);
+ /* AHHH, much better now! the clueless won't notice anyways */
+ gtk_rc_parse_string("gtk-key-theme-name = \"Emacs\"");
+
if (ve_string_empty (g_getenv ("GDM_IS_LOCAL")))
disable_sys_config_chooser_buttons = TRUE;
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]