diff -upr gdm-2.16.1-pre/config/gdm.conf.in gdm-2.16.1-post/config/gdm.conf.in --- gdm-2.16.1-pre/config/gdm.conf.in 2006-11-08 00:02:48.000000000 -0600 +++ gdm-2.16.1-post/config/gdm.conf.in 2006-11-08 00:02:57.000000000 -0600 @@ -498,6 +498,9 @@ SoundOnLogin=false # list of libraries, one per line, and load each library in the file. PreFetchProgram=@GDMPREFETCHCMD@ +# Set to true to show the domain login GUI elements. +#ShowDomain=false + # The chooser is what's displayed when a user wants an indirect XDMCP session, # or selects Run XDMCP chooser from the system menu [chooser] diff -upr gdm-2.16.1-pre/config/gdm.conf.in.orig gdm-2.16.1-post/config/gdm.conf.in.orig --- gdm-2.16.1-pre/config/gdm.conf.in.orig 2006-08-03 12:36:26.000000000 -0500 +++ gdm-2.16.1-post/config/gdm.conf.in.orig 2006-11-08 00:02:57.000000000 -0600 @@ -67,11 +67,11 @@ TimedLoginDelay=30 # The greeter for local (non-xdmcp) logins. Change gdmlogin to gdmgreeter to # get the new graphical greeter. -#Greeter=@libexecdir@/gdmlogin +Greeter=@libexecdir@/gdmgreeter # The greeter for xdmcp logins, usually you want a less graphically intensive # greeter here so it's better to leave this with gdmlogin -#RemoteGreeter=@libexecdir@/gdmlogin +RemoteGreeter=@libexecdir@/gdmgreeter # Launch the greeter with an additional list of colon separated GTK+ modules. # This is useful for enabling additional feature support e.g. GNOME @@ -85,10 +85,12 @@ TimedLoginDelay=30 # This value will be overridden with the value from /etc/default/login if it # contains "ROOT=". #DefaultPath=@GDM_USER_PATH@ +DefaultPath=/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/var/lib/dosemu:/usr/games:/opt/bin:/opt/kde3/bin:/opt/kde2/bin:/opt/kde/bin:/usr/openwin/bin:/opt/cross/bin # Default path for root. The profile scripts will likely override this value. # This value will be overridden with the value from /etc/default/login if it # contains "SUROOT=". #RootPath=/sbin:/usr/sbin:@GDM_USER_PATH@ +RootPath=/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/var/lib/dosemu:/usr/games:/opt/bin:/opt/kde3/bin:/opt/kde2/bin:/opt/kde/bin:/usr/openwin/bin:/opt/cross/bin # If you are having trouble with using a single server for a long time and want # GDM to kill/restart the server, turn this on. On Solaris, this value is @@ -127,6 +129,9 @@ XKeepsCrashing=@gdmconfdir@/XKeepsCrashi #RebootCommand=@REBOOT_COMMAND@ #HaltCommand=@HALT_COMMAND@ #SuspendCommand=@SUSPEND_COMMAND@ +RebootCommand=/sbin/shutdown -r now +HaltCommand=/sbin/shutdown -h now +SuspendCommand=/usr/bin/powersave --suspend-to-disk # Probably should not touch the below this is the standard setup. ServAuthDir=@authdir@ # This is our standard startup script. A bit different from a normal X @@ -137,7 +142,7 @@ BaseXsession=@gdmconfdir@/Xsession # really a PATH style variable since 2.4.4.2 to allow actual interoperability # with KDM. Note that /Sessions is there for backwards # compatibility reasons with 2.4.4.x. -#SessionDesktopDir=/etc/X11/sessions/:@dmconfdir@/Sessions/:@datadir@/gdm/BuiltInSessions/:@datadir@/xsessions/ +SessionDesktopDir=/usr/share/xsessions/:@EXPANDED_SYSCONFDIR@/dm/Sessions/:@EXPANDED_DATADIR@/gdm/BuiltInSessions/ # This is the default .desktop session. One of the ones in SessionDesktopDir #DefaultSession=gnome.desktop # Better leave this blank and HOME will be used. You can use syntax ~/ below @@ -220,7 +225,7 @@ RelaxPermissions=0 # example, home directories owned by some other user. CheckDirOwner=true # Number of seconds to wait after a failed login -#RetryDelay=1 +RetryDelay=1 # Maximum size of a file we wish to read. This makes it hard for a user to DoS # us by using a large file. #UserMaxFile=65536 @@ -281,17 +286,18 @@ Enable=false #PingIntervalSeconds=15 # The port. 177 is the standard port so better keep it that way. #Port=177 -# Willing script, none is shipped and by default we'll send hostname system id. -# But if you supply something here, the output of this script will be sent as -# status of this host so that the chooser can display it. You could for -# example send load, or mail details for some user, or some such. -#Willing=@gdmconfdir@/Xwilling +#Willing script, none is shipped, X11's one is used by default. If +# none is present we'll send hostname system id. But if you supply +# something here, the output of this script will be sent as status of +# this host so that the chooser can display it. You could for example +# send load, or mail details for some user, or some such. +Willing=/etc/X11/xdm/Xwilling [gui] # The specific gtkrc file we use. It should be the full path to the gtkrc that # we need. Unless you need a specific gtkrc that doesn't correspond to a # specific theme, then just use the GtkTheme key. -#GtkRC=@datadir@/themes/Default/gtk-2.0/gtkrc +GtkRC=@datadir@/themes/Industrial/gtk-2.0/gtkrc # The GTK+ theme to use for the GUI. #GtkTheme=Default @@ -318,7 +324,7 @@ Enable=false #TitleBar=true # Don't allow user to move the standard login window. Only makes sense if # TitleBar is on. -#LockPosition=false +LockPosition=true # Set a position for the standard login window rather then just centering the # window. If you enter negative values for the position it is taken as an # offset from the right or bottom edge. @@ -339,7 +345,7 @@ Browser=false # User ID's less than the MinimalUID value will not be included in the face # browser or in the gdmselection list for Automatic/Timed login. They will not # be displayed regardless of the settings for Include and Exclude. -#MinimalUID=100 +MinimalUID=500 # Users listed in Include will be included in the face browser and in the # gdmsetup selection list for Automatic/Timed login. Users should be separated # by commas. @@ -356,7 +362,7 @@ Browser=false # large numbers of users and this feature should not be used in such # environments. The setting of IncludeAll does nothing if Include is set to a # non-empty value. -#IncludeAll=false +IncludeAll=true # If user or user.png exists in this dir it will be used as his picture. #GlobalFaceDir=@datadir@/pixmaps/faces/ @@ -370,7 +376,7 @@ Browser=false #ChooserButtonLogo=@pixmapdir@/gdm-foot-logo.png # The standard greeter should shake if a user entered the wrong username or # password. Kind of cool looking -#Quiver=true +Quiver=false # The Actions menu (formerly system menu) is shown in the greeter, this is the # menu that contains reboot, shutdown, suspend, config and chooser. None of @@ -407,12 +413,12 @@ DefaultRemoteWelcome=true # Background settings for the standard greeter: # Type can be 0=None, 1=Image & Color, 2=Color, 3=Image #BackgroundType=2 -#BackgroundImage= +BackgroundImage=0 #BackgroundScaleToFit=true # The Standard greeter (gdmlogin) uses BackgroundColor as the background # color, while the themed greeter (gdmgreeter) uses GraphicalThemedColor # as the background color. -BackgroundColor=#76848F +BackgroundColor=#000000 GraphicalThemedColor=#76848F # XDMCP session should only get a color, this is the sanest setting since you # don't want to take up too much bandwidth @@ -454,7 +460,7 @@ GraphicalThemedColor=#76848F # list then provide a list that is delimited by /: to the GraphicalThemes # key and set GraphicalThemeRand to true. Otherwise use GraphicalTheme # and specify just one theme. -#GraphicalTheme=circles +GraphicalTheme=GDM-SuSE #GraphicalThemes=circles/:happygnome GraphicalThemeDir=@datadir@/gdm/themes/ GraphicalThemeRand=false @@ -471,6 +477,7 @@ GraphicalThemeRand=false # executable (see daemon/SoundProgram) it will play that file instead of just # beeping. #SoundOnLogin=true +SoundOnLogin=false #SoundOnLoginFile= # If SoundOnLoginSuccess, then the greeter will play a sound (as above) when a # user successfully logs in. @@ -558,7 +565,7 @@ Gestures=false # Definition of the standard X server. [server-Standard] name=Standard server -command=@X_SERVER@ @X_CONFIG_OPTIONS@ @XEVIE_OPTION@ +command=@X_SERVER@ @X_CONFIG_OPTIONS@ @XEVIE_OPTION@ -br flexible=true # Indicates that the X server should be started at a different process # priority. Values can be any integer value accepted by the setpriority C diff -upr gdm-2.16.1-pre/configure.ac gdm-2.16.1-post/configure.ac --- gdm-2.16.1-pre/configure.ac 2006-11-08 00:02:48.000000000 -0600 +++ gdm-2.16.1-post/configure.ac 2006-11-08 00:02:57.000000000 -0600 @@ -844,6 +844,9 @@ AC_SUBST(GDMPREFETCH) AC_SUBST(GDMPREFETCHLIST) AC_SUBST(GDMPREFETCHCMD) +GDM_SCRATCH_DIR="${localstatedir}/gdm" +AC_DEFINE_UNQUOTED(GDM_SCRATCH_DIR, "$GDM_SCRATCH_DIR", [GDM scratch dir]) + AC_ARG_ENABLE(secureremote, [ --enable-secureremote=[yes/no] Enable to offer a secure X connection through ssh [default=no]],, enable_secureremote=no) diff -upr gdm-2.16.1-pre/daemon/gdmconfig.c gdm-2.16.1-post/daemon/gdmconfig.c --- gdm-2.16.1-pre/daemon/gdmconfig.c 2006-07-17 13:43:51.000000000 -0500 +++ gdm-2.16.1-post/daemon/gdmconfig.c 2006-11-08 00:04:46.000000000 -0600 @@ -231,6 +231,7 @@ static gint GdmFlexiReapDelayMinutes; static gint GdmBackgroundProgramInitialDelay = 30; static gint GdmBackgroundProgramRestartDelay = 30; +static gboolean GdmShowDomain; static gboolean GdmAllowGtkThemeChange; static gboolean GdmTitleBar; static gboolean GdmIncludeAll; @@ -348,6 +349,7 @@ gdm_config_init (void) realkey_hash = g_hash_table_new (g_str_hash, g_str_equal); /* boolean values */ + gdm_config_add_hash (GDM_KEY_SHOW_DOMAIN, &GdmShowDomain, &bool_type); gdm_config_add_hash (GDM_KEY_ALLOW_REMOTE_ROOT, &GdmAllowRemoteRoot, &bool_type); gdm_config_add_hash (GDM_KEY_ALLOW_ROOT, &GdmAllowRoot, &bool_type); gdm_config_add_hash (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN, diff -upr gdm-2.16.1-pre/daemon/gdm.h gdm-2.16.1-post/daemon/gdm.h --- gdm-2.16.1-pre/daemon/gdm.h 2006-08-23 22:47:43.000000000 -0500 +++ gdm-2.16.1-post/daemon/gdm.h 2006-11-08 00:02:57.000000000 -0600 @@ -384,6 +384,8 @@ enum { #define GDM_KEY_GRAPHICAL_THEME_DIR "greeter/GraphicalThemeDir=" DATADIR "/gdm/themes/" #define GDM_KEY_GRAPHICAL_THEMED_COLOR "greeter/GraphicalThemedColor=#76848F" +#define GDM_KEY_SHOW_DOMAIN "greeter/ShowDomain=false" + #define GDM_KEY_INFO_MSG_FILE "greeter/InfoMsgFile=" #define GDM_KEY_INFO_MSG_FONT "greeter/InfoMsgFont=" @@ -725,6 +727,7 @@ void gdm_final_cleanup (void); #define GDM_NOTIFY_TIMED_LOGIN_DELAY "TimedLoginDelay" /* */ #define GDM_NOTIFY_TIMED_LOGIN_ENABLE "TimedLoginEnable" /* */ #define GDM_NOTIFY_DISALLOW_TCP "DisallowTCP" /* */ +#define GDM_NOTIFY_SHOW_DOMAIN "ShowDomain" /* */ #define GDM_NOTIFY_SOUND_ON_LOGIN_FILE "SoundOnLoginFile" /* */ #define GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE "SoundOnLoginSuccessFile" /* */ #define GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE "SoundOnLoginFailureFile" /* */ diff -upr gdm-2.16.1-pre/daemon/verify-pam.c gdm-2.16.1-post/daemon/verify-pam.c --- gdm-2.16.1-pre/daemon/verify-pam.c 2006-06-09 16:07:41.000000000 -0500 +++ gdm-2.16.1-post/daemon/verify-pam.c 2006-11-08 00:02:57.000000000 -0600 @@ -57,6 +57,8 @@ static char *tmp_PAM_USER = NULL; /* this is another hack */ static gboolean did_we_ask_for_password = FALSE; +static gboolean is_account_disabled = FALSE; +static gboolean is_account_expired = FALSE; static char *selected_user = NULL; @@ -430,6 +432,7 @@ perhaps_translate_message (const char *m g_hash_table_insert (hash, "You are required to change your password immediately (password aged)", _("You are required to change your password immediately (password aged)")); g_hash_table_insert (hash, "You are required to change your password immediately (root enforced)", _("You are required to change your password immediately (root enforced)")); g_hash_table_insert (hash, "Your account has expired; please contact your system administrator", _("Your account has expired; please contact your system administrator")); + g_hash_table_insert (hash, "Your account is disabled. Please contact your system administrator", _("Your account is disabled. Please contact your system administrator")); g_hash_table_insert (hash, "No password supplied", _("No password supplied")); g_hash_table_insert (hash, "Password unchanged", _("Password unchanged")); g_hash_table_insert (hash, "Can not get username", _("Can not get username")); @@ -502,8 +505,9 @@ gdm_verify_pam_conv (int num_msg, struct for (replies = 0; replies < num_msg; replies++) { gboolean islogin = FALSE; - const char *m = msg[replies]->msg; - m = perhaps_translate_message (m); + const char *m_untranslated = msg[replies]->msg; + const char *m; + m = perhaps_translate_message (m_untranslated); switch (msg[replies]->msg_style) { @@ -589,6 +593,12 @@ gdm_verify_pam_conv (int num_msg, struct case PAM_ERROR_MSG: /* PAM sent a message that should displayed to the user */ + + if (strstr (m_untranslated, "account is disabled")) + is_account_disabled = TRUE; + else if (strstr (m_untranslated, "account has expired")) + is_account_expired = TRUE; + gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, m); reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = NULL; @@ -1125,7 +1135,11 @@ authenticate_again: /* Only give this message if we actually asked for password, otherwise it would be silly to say that the password may have been wrong */ - if (did_we_ask_for_password) { + if (is_account_disabled) { + basemsg = _("\nYour account has been disabled."); + } else if (is_account_expired) { + basemsg = _("\nYour account has expired."); + } else if (did_we_ask_for_password) { basemsg = _("\nIncorrect username or password. " "Letters must be typed in the correct " "case."); @@ -1134,7 +1148,7 @@ authenticate_again: "Letters must be typed in the correct " "case."); } - if (is_capslock) { + if (is_capslock && !is_account_disabled && !is_account_expired) { msg = g_strconcat (basemsg, " ", _("Caps Lock is on."), NULL); @@ -1250,6 +1264,8 @@ gdm_verify_setup_user (GdmDisplay *d, co /* Start authentication session */ did_we_ask_for_password = FALSE; + is_account_disabled = FALSE; + is_account_expired = FALSE; if ((pamerr = pam_authenticate (pamh, null_tok)) != PAM_SUCCESS) { if (gdm_slave_action_pending ()) { gdm_error (_("Couldn't authenticate user")); diff -upr gdm-2.16.1-pre/gui/greeter/greeter.c gdm-2.16.1-post/gui/greeter/greeter.c --- gdm-2.16.1-pre/gui/greeter/greeter.c 2006-11-08 00:02:48.000000000 -0600 +++ gdm-2.16.1-post/gui/greeter/greeter.c 2006-11-08 00:02:57.000000000 -0600 @@ -121,6 +121,53 @@ get_random_theme () return theme; } +static gchar *errdlg_message = NULL; + +static void +show_errdlg_messages (void) +{ + gchar *tmp; + GtkWidget *dlg; + + if (!errdlg_message) + return; + + /* we should be now fine for focusing new windows */ + gdm_wm_focus_new_windows (TRUE); + + tmp = ve_locale_to_utf8 (errdlg_message); + dlg = ve_hig_dialog_new (NULL /* parent */, + GTK_DIALOG_MODAL /* flags */, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + tmp, + ""); + g_free (tmp); + g_free (errdlg_message); + errdlg_message = NULL; + + 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 (); +} + +static void +append_errdlg_message (const gchar *message) +{ + if (errdlg_message) { + gchar *tmp; + + tmp = g_strjoin ("\n\n", errdlg_message, message, NULL); + g_free (errdlg_message); + errdlg_message = tmp; + } else { + errdlg_message = g_strdup (message); + } +} + static gboolean greeter_ctrl_handler (GIOChannel *source, GIOCondition cond, @@ -184,6 +231,8 @@ process_operation (guchar op_code, break; case GDM_PROMPT: + show_errdlg_messages (); + tmp = ve_locale_to_utf8 (args); if (tmp != NULL && strcmp (tmp, _("Username:")) == 0) { gdm_common_login_sound (gdm_config_get_string (GDM_KEY_SOUND_PROGRAM), @@ -205,6 +254,8 @@ process_operation (guchar op_code, break; case GDM_NOECHO: + show_errdlg_messages (); + tmp = ve_locale_to_utf8 (args); if (tmp != NULL && strcmp (tmp, _("Password:")) == 0) @@ -217,6 +268,8 @@ process_operation (guchar op_code, break; case GDM_MSG: + show_errdlg_messages (); + tmp = ve_locale_to_utf8 (args); greeter_item_pam_message (tmp); g_free (tmp); @@ -225,6 +278,8 @@ process_operation (guchar op_code, break; case GDM_ERRBOX: + show_errdlg_messages (); + tmp = ve_locale_to_utf8 (args); greeter_item_pam_error (tmp); g_free (tmp); @@ -234,30 +289,17 @@ process_operation (guchar op_code, break; case GDM_ERRDLG: - /* we should be now fine for focusing new windows */ - gdm_wm_focus_new_windows (TRUE); - tmp = ve_locale_to_utf8 (args); - dlg = ve_hig_dialog_new (NULL /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - tmp, - ""); + append_errdlg_message (tmp); g_free (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 (); - printf ("%c\n", STX); fflush (stdout); break; case GDM_SESS: + show_errdlg_messages (); + tmp = ve_locale_to_utf8 (args); session = gdm_session_lookup (tmp); g_free (tmp); @@ -274,6 +316,8 @@ process_operation (guchar op_code, break; case GDM_LANG: + show_errdlg_messages (); + language = greeter_language_get_language (args); if (greeter_language_get_save_language () == GTK_RESPONSE_CANCEL) printf ("%c%s\n", STX, GDM_RESPONSE_CANCEL); @@ -284,6 +328,8 @@ process_operation (guchar op_code, break; case GDM_SSESS: + show_errdlg_messages (); + if (gdm_get_save_session () == GTK_RESPONSE_YES) printf ("%cY\n", STX); else @@ -293,6 +339,8 @@ process_operation (guchar op_code, break; case GDM_SLANG: + show_errdlg_messages (); + if (greeter_language_get_save_language () == GTK_RESPONSE_YES) printf ("%cY\n", STX); else @@ -325,6 +373,8 @@ process_operation (guchar op_code, break; case GDM_QUIT: + show_errdlg_messages (); + greeter_item_timed_stop (); if (require_quarter) { @@ -429,6 +479,8 @@ process_operation (guchar op_code, break; case GDM_SAVEDIE: + show_errdlg_messages (); + /* Set busy cursor */ gdm_common_setup_cursor (GDK_WATCH); @@ -448,6 +500,8 @@ process_operation (guchar op_code, break; default: + show_errdlg_messages (); + gdm_common_fail_greeter ("Unexpected greeter command received: '%c'", op_code); break; } @@ -773,6 +827,7 @@ gdm_read_config (void) gdm_config_get_bool (GDM_KEY_SOUND_ON_LOGIN); gdm_config_get_bool (GDM_KEY_DEFAULT_WELCOME); gdm_config_get_bool (GDM_KEY_DEFAULT_REMOTE_WELCOME); + gdm_config_get_bool (GDM_KEY_SHOW_DOMAIN); /* Keys not to include in reread_config */ gdm_config_get_string (GDM_KEY_SESSION_DESKTOP_DIR); @@ -832,7 +887,8 @@ greeter_reread_config (int sig, gpointer gdm_config_reload_bool (GDM_KEY_GRAPHICAL_THEME_RAND) || gdm_config_reload_bool (GDM_KEY_SHOW_LAST_SESSION) || gdm_config_reload_bool (GDM_KEY_ALLOW_ROOT) || - gdm_config_reload_bool (GDM_KEY_ALLOW_REMOTE_ROOT)) { + gdm_config_reload_bool (GDM_KEY_ALLOW_REMOTE_ROOT) || + gdm_config_reload_bool (GDM_KEY_SHOW_DOMAIN)) { /* Set busy cursor */ gdm_common_setup_cursor (GDK_WATCH); diff -upr gdm-2.16.1-pre/gui/greeter/greeter_canvas_item.c gdm-2.16.1-post/gui/greeter/greeter_canvas_item.c --- gdm-2.16.1-pre/gui/greeter/greeter_canvas_item.c 2006-11-08 00:02:48.000000000 -0600 +++ gdm-2.16.1-post/gui/greeter/greeter_canvas_item.c 2006-11-08 00:02:57.000000000 -0600 @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include #include @@ -40,6 +42,10 @@ #include "greeter_canvas_item.h" #include "greeter_configuration.h" #include "greeter_canvas_text.h" +#include "greeter_parser.h" + +#define WBINFO_DOMAINS_MAX 64 +#define WBINFO_READ_MAX 256 static void apply_tint (GdkPixbuf *pixbuf, guint32 tint_color) @@ -376,6 +382,189 @@ set_root_pixmap (GdkPixmap *pixmap) return FALSE; } +gboolean greeter_can_do_domain_login = FALSE; +gchar *greeter_domain_separator = NULL; + +gboolean greeter_wbinfo_was_run = FALSE; +gboolean greeter_wbinfo_is_running = FALSE; +GPid greeter_wbinfo_pid; +GIOChannel *greeter_wbinfo_channel; +GString *greeter_wbinfo_output; + +static void +wbinfo_end (void) +{ + GreeterItemInfo *domain_entry_item_info; + GtkWidget *domain_entry = NULL; + gint wbinfo_status = 0; + gchar *wbinfo_output; + GtkListStore *domain_list_store; + gchar **tokens = NULL; + gchar *own_domain = NULL; + gint select_index = 0; + GtkTreeIter iter; + const gchar *text; + gint i; + + if (!greeter_wbinfo_is_running) + return; + + greeter_wbinfo_is_running = FALSE; + waitpid (greeter_wbinfo_pid, &wbinfo_status, 0); + g_spawn_close_pid (greeter_wbinfo_pid); + + wbinfo_output = g_string_free (greeter_wbinfo_output, FALSE); + + domain_entry_item_info = greeter_lookup_id ("domain-entry"); + if (domain_entry_item_info && domain_entry_item_info->item && + GNOME_IS_CANVAS_WIDGET (domain_entry_item_info->item)) { + domain_entry = GNOME_CANVAS_WIDGET (domain_entry_item_info->item)->widget; + } else { + g_free (wbinfo_output); + return; + } + + /* Set up the domain store model */ + + domain_list_store = gtk_list_store_new (1, G_TYPE_STRING); + + /* The "local login" entry */ + + gtk_list_store_append (domain_list_store, &iter); + gtk_list_store_set (domain_list_store, &iter, + 0, _(""), + -1); + + /* Process wbinfo output, if any */ + + if (WEXITSTATUS (wbinfo_status) == 0 && wbinfo_output && *wbinfo_output) { + /* The first line of output should be the domain separator, + * and any remaining lines are trusted domains. */ + tokens = g_strsplit_set (wbinfo_output, "\n\r", WBINFO_DOMAINS_MAX + 1); + } + + g_free (wbinfo_output); + g_free (greeter_domain_separator); + greeter_domain_separator = NULL; + + if (tokens && tokens [0]) { + greeter_can_do_domain_login = TRUE; + greeter_domain_separator = g_strdup (tokens [0]); + + own_domain = tokens [1]; + + /* Generate a sorted list of domains for the domain selector combo. */ + + g_qsort_with_data (&tokens [1], + g_strv_length (tokens) - 1, + sizeof (gchar *), + (GCompareDataFunc) g_ascii_strcasecmp, + NULL); + + for (i = 1; tokens [i]; i++) { + /* Ensure no blank entries */ + if (!strlen (tokens [i])) + continue; + + gtk_list_store_append (domain_list_store, &iter); + gtk_list_store_set (domain_list_store, &iter, + 0, tokens [i], + -1); + + if (tokens [i] == own_domain) + select_index = i; + } + + } else { + greeter_can_do_domain_login = FALSE; + } + + if (tokens) + g_strfreev (tokens); + + /* Assign model and default selection to widget */ + + gtk_combo_box_set_model (GTK_COMBO_BOX (domain_entry), + GTK_TREE_MODEL (domain_list_store)); + gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (domain_entry), 0); + + /* Default to our own domain, but only if the entry was empty */ + text = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (domain_entry)))); + if (!text || !*text) + gtk_combo_box_set_active (GTK_COMBO_BOX (domain_entry), select_index); + + g_object_unref (domain_list_store); +} + +static gboolean +wbinfo_on_output (GIOChannel *channel, GIOCondition condition, gpointer data) +{ + gchar buf [WBINFO_READ_MAX]; + gsize bytes_read; + GIOStatus status; + + status = g_io_channel_read_chars (channel, buf, WBINFO_READ_MAX, &bytes_read, NULL); + + if (bytes_read < 1) { + wbinfo_end (); + return FALSE; + } + + g_string_append_len (greeter_wbinfo_output, buf, bytes_read); + return TRUE; +} + +static void +wbinfo_begin (void) +{ + gchar *wbinfo_args [] = { "wbinfo", "--separator", "--own-domain", "--trusted-domains", NULL }; + gchar *wbinfo_env [] = { NULL }; + gint wbinfo_stdout_fd; + + if (greeter_wbinfo_was_run) + return; + + greeter_wbinfo_was_run = TRUE; + + /* Lame guess, in case winbind isn't running, but gets started later. This + * is a workaround for testing and broken systems. */ + greeter_domain_separator = g_strdup ("\\"); + + if (!g_spawn_async_with_pipes ("/", + wbinfo_args, + wbinfo_env, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_DO_NOT_REAP_CHILD, + NULL /* child setup function */, + NULL /* child setup user_data */, + &greeter_wbinfo_pid, + NULL /* &wbinfo_stdin_fd */, + &wbinfo_stdout_fd, + NULL /* &wbinfo_stderr_fd */, + NULL)) + return; + + greeter_wbinfo_is_running = TRUE; + greeter_wbinfo_output = g_string_new (""); + + fcntl (wbinfo_stdout_fd, F_SETFL, O_NONBLOCK); + + greeter_wbinfo_channel = g_io_channel_unix_new (wbinfo_stdout_fd); + g_io_channel_set_encoding (greeter_wbinfo_channel, NULL, NULL); + g_io_channel_set_close_on_unref (greeter_wbinfo_channel, TRUE); + g_io_add_watch (greeter_wbinfo_channel, G_IO_IN | G_IO_HUP, wbinfo_on_output, NULL); + g_io_channel_unref (greeter_wbinfo_channel); /* Watch holds remaining ref */ +} + +static gboolean +deselect_entry_text (GtkEntry *entry) +{ + gtk_editable_select_region (GTK_EDITABLE (entry), 0, 0); + gtk_editable_set_position (GTK_EDITABLE (entry), -1); + + return FALSE; +} + void greeter_item_create_canvas_item (GreeterItemInfo *item) { @@ -661,6 +850,48 @@ greeter_item_create_canvas_item (Greeter break; + case GREETER_ITEM_TYPE_COMBO_BOX_ENTRY: + entry = gtk_combo_box_entry_new (); + + gtk_widget_set_name (entry, "domain-entry"); + + gtk_entry_set_has_frame (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (entry))), FALSE); + gtk_widget_modify_font (entry, item->data.text.fonts[GREETER_ITEM_STATE_NORMAL]); + + get_gdk_color_from_rgb (&c, item->data.text.colors[GREETER_ITEM_STATE_NORMAL]); + gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &c); + + item->item = gnome_canvas_item_new (group, + GNOME_TYPE_CANVAS_WIDGET, + "widget", entry, + "x", x1, + "y", y1, + "height", (double)rect.height, + "width", (double)rect.width, + NULL); + + /* cursor blinking is evil on remote displays, don't do it forever */ + gdm_common_setup_blinking_entry (gtk_bin_get_child (GTK_BIN (entry))); + + /* Recall the last used domain */ + if (g_file_get_contents (GDM_SCRATCH_DIR "/last_domain", &text, NULL, NULL)) { + GtkWidget *temp_entry; + + temp_entry = gtk_bin_get_child (GTK_BIN (entry)); + + gtk_entry_set_text (GTK_ENTRY (temp_entry), text); + + /* The set text gets selected. It looks bad. Avoid that. */ + g_idle_add_full (G_PRIORITY_LOW, (GSourceFunc) deselect_entry_text, temp_entry, NULL); + + g_free (text); + } + + /* Query wbinfo */ + wbinfo_begin (); + + break; + case GREETER_ITEM_TYPE_LIST: /* Note a list type must be setup later and we will add the list store * to it then, depending on the type. Likely userlist is the Only in gdm-2.16.1-post/gui/greeter: greeter_canvas_item.c.orig diff -upr gdm-2.16.1-pre/gui/greeter/greeter_configuration.h gdm-2.16.1-post/gui/greeter/greeter_configuration.h --- gdm-2.16.1-pre/gui/greeter/greeter_configuration.h 2005-04-18 21:57:56.000000000 -0500 +++ gdm-2.16.1-post/gui/greeter/greeter_configuration.h 2006-11-08 00:02:57.000000000 -0600 @@ -62,6 +62,7 @@ extern gchar *GdmSoundOnLoginFailureFile extern gboolean GdmSoundOnLoginReady; extern gboolean GdmSoundOnLoginSuccess; extern gboolean GdmSoundOnLoginFailure; +extern gboolean GdmShowDomain; extern gboolean GDM_IS_LOCAL; extern gboolean DOING_GDM_DEVELOPMENT; diff -upr gdm-2.16.1-pre/gui/greeter/greeter.h gdm-2.16.1-post/gui/greeter/greeter.h --- gdm-2.16.1-pre/gui/greeter/greeter.h 2005-10-06 16:30:26.000000000 -0500 +++ gdm-2.16.1-post/gui/greeter/greeter.h 2006-11-08 00:02:57.000000000 -0600 @@ -27,6 +27,9 @@ extern GtkWidget *window; extern gboolean greeter_probably_login_prompt; +extern gboolean greeter_can_do_domain_login; +extern gchar *greeter_domain_separator; + void greeter_ignore_buttons (gboolean val); #endif diff -upr gdm-2.16.1-pre/gui/greeter/greeter_item.c gdm-2.16.1-post/gui/greeter/greeter_item.c --- gdm-2.16.1-pre/gui/greeter/greeter_item.c 2006-04-26 21:10:16.000000000 -0500 +++ gdm-2.16.1-post/gui/greeter/greeter_item.c 2006-11-08 00:02:57.000000000 -0600 @@ -209,6 +209,10 @@ greeter_item_is_visible (GreeterItemInfo strcmp (info->show_type, "suspend") == 0)) return FALSE; + if ( ! gdm_config_get_bool (GDM_KEY_SHOW_DOMAIN) && + g_str_has_prefix (info->show_type, "domain")) + return FALSE; + if (( ! gdm_config_get_bool (GDM_KEY_TIMED_LOGIN_ENABLE) || ve_string_empty (gdm_config_get_string (GDM_KEY_TIMED_LOGIN))) && (info->show_type != NULL && diff -upr gdm-2.16.1-pre/gui/greeter/greeter_item.h gdm-2.16.1-post/gui/greeter/greeter_item.h --- gdm-2.16.1-pre/gui/greeter/greeter_item.h 2006-04-26 21:10:16.000000000 -0500 +++ gdm-2.16.1-post/gui/greeter/greeter_item.h 2006-11-08 00:02:57.000000000 -0600 @@ -47,7 +47,8 @@ enum _GreeterItemType { GREETER_ITEM_TYPE_LABEL, GREETER_ITEM_TYPE_ENTRY, GREETER_ITEM_TYPE_LIST, - GREETER_ITEM_TYPE_BUTTON + GREETER_ITEM_TYPE_BUTTON, + GREETER_ITEM_TYPE_COMBO_BOX_ENTRY }; /* Make sure to adjust the bitfield in the structure if @@ -147,7 +148,7 @@ struct _GreeterItemInfo { union { /* Note: we want to have alphas, colors and have_color coincide for all types that have it */ -#define GREETER_ITEM_TYPE_IS_TEXT(info) ((info)->item_type == GREETER_ITEM_TYPE_LABEL || (info)->item_type == GREETER_ITEM_TYPE_ENTRY) +#define GREETER_ITEM_TYPE_IS_TEXT(info) ((info)->item_type == GREETER_ITEM_TYPE_LABEL || (info)->item_type == GREETER_ITEM_TYPE_ENTRY || (info)->item_type == GREETER_ITEM_TYPE_COMBO_BOX_ENTRY) struct { guint8 alphas[GREETER_ITEM_STATE_MAX]; guint32 colors[GREETER_ITEM_STATE_MAX]; diff -upr gdm-2.16.1-pre/gui/greeter/greeter_item_pam.c gdm-2.16.1-post/gui/greeter/greeter_item_pam.c --- gdm-2.16.1-pre/gui/greeter/greeter_item_pam.c 2006-06-09 16:07:42.000000000 -0500 +++ gdm-2.16.1-post/gui/greeter/greeter_item_pam.c 2006-11-08 00:02:57.000000000 -0600 @@ -36,6 +36,7 @@ #include "gdm.h" #include "gdmwm.h" #include "gdmcommon.h" +#include "gdmconfig.h" static gboolean messages_to_give = FALSE; static gboolean replace_msg = TRUE; @@ -115,11 +116,29 @@ set_text (GreeterItemInfo *info, const c info->item); } +static void +domain_entry_set_sensitive (gboolean sensitive) +{ + if (gdm_config_get_bool (GDM_KEY_SHOW_DOMAIN)) + { + GreeterItemInfo *domain_entry_item_info; + GtkWidget *domain_entry = NULL; + + domain_entry_item_info = greeter_lookup_id ("domain-entry"); + if (domain_entry_item_info && domain_entry_item_info->item && + GNOME_IS_CANVAS_WIDGET (domain_entry_item_info->item)) + domain_entry = GNOME_CANVAS_WIDGET (domain_entry_item_info->item)->widget; + + if (domain_entry) + gtk_widget_set_sensitive (domain_entry, sensitive); + } +} + void greeter_item_pam_login (GtkEntry *entry, GreeterItemInfo *info) { const char *str; - char *tmp; + char *tmp, *tmp2; GreeterItemInfo *error_info; greeter_ignore_buttons (TRUE); @@ -146,6 +165,7 @@ greeter_item_pam_login (GtkEntry *entry, } gtk_widget_set_sensitive (GTK_WIDGET (entry), FALSE); + domain_entry_set_sensitive (FALSE); /* clear the err_box */ if (err_box_clear_handler > 0) @@ -160,6 +180,33 @@ greeter_item_pam_login (GtkEntry *entry, } tmp = ve_locale_from_utf8 (str); + + /* Prepend the domain if applicable */ + if (greeter_probably_login_prompt && gdm_config_get_bool (GDM_KEY_SHOW_DOMAIN)) + { + GreeterItemInfo *domain_entry_item_info; + GtkWidget *domain_entry = NULL; + + domain_entry_item_info = greeter_lookup_id ("domain-entry"); + if (domain_entry_item_info && domain_entry_item_info->item && + GNOME_IS_CANVAS_WIDGET (domain_entry_item_info->item)) + domain_entry = GNOME_CANVAS_WIDGET (domain_entry_item_info->item)->widget; + + if (domain_entry && (str = gtk_combo_box_get_active_text (GTK_COMBO_BOX (domain_entry))) && *str && + strcmp (str, _(""))) + { + g_file_set_contents (GDM_SCRATCH_DIR "/last_domain", str, strlen (str), NULL); + + tmp2 = g_strdup_printf ("%s%s%s", str, greeter_domain_separator, tmp); + g_free (tmp); + tmp = tmp2; + } + else + { + g_remove (GDM_SCRATCH_DIR "/last_domain"); + } + } + printf ("%c%s\n", STX, tmp); fflush (stdout); g_free (tmp); @@ -213,6 +260,7 @@ greeter_item_pam_setup (void) /* initially insensitive */ gtk_widget_set_sensitive (entry, FALSE); + domain_entry_set_sensitive (FALSE); } g_signal_connect (entry, "activate", @@ -252,6 +300,9 @@ greeter_item_pam_prompt (const char *mes gtk_entry_set_max_length (GTK_ENTRY (entry), entry_len); gtk_entry_set_text (GTK_ENTRY (entry), ""); gtk_widget_grab_focus (entry); + + /* Domain selector should only be accessed when entering the user name */ + domain_entry_set_sensitive (entry_visible); } messages_to_give = FALSE; diff -upr gdm-2.16.1-pre/gui/greeter/greeter_parser.c gdm-2.16.1-post/gui/greeter/greeter_parser.c --- gdm-2.16.1-pre/gui/greeter/greeter_parser.c 2006-08-02 21:32:39.000000000 -0500 +++ gdm-2.16.1-post/gui/greeter/greeter_parser.c 2006-11-08 00:02:57.000000000 -0600 @@ -394,6 +394,11 @@ parse_stock (xmlNodePtr node, g_free (*translated_text); *translated_text = g_strdup (_("Username:")); } + else if (g_ascii_strcasecmp ((char *) prop, "domain-label") == 0) + { + g_free (*translated_text); + *translated_text = g_strdup (_("Domain:")); + } else if (g_ascii_strcasecmp ((char *) prop, "ok") == 0) { g_free (*translated_text); @@ -1552,6 +1557,15 @@ parse_entry (xmlNodePtr node, } static gboolean +parse_combo_box_entry (xmlNodePtr node, + GreeterItemInfo *info, + GError **error) +{ + /* A ComboBoxEntry is just an Entry with a dropdown list */ + return parse_entry (node, info, error); +} + +static gboolean parse_items (xmlNodePtr node, GList **items_out, GreeterItemInfo *parent, @@ -1606,6 +1620,8 @@ parse_items (xmlNodePtr node, item_type = GREETER_ITEM_TYPE_LIST; else if (strcmp ((char *) type, "button") == 0) item_type = GREETER_ITEM_TYPE_BUTTON; + else if (strcmp ((char *) type, "combo-box-entry") == 0) + item_type = GREETER_ITEM_TYPE_COMBO_BOX_ENTRY; else { g_set_error (error, @@ -1650,6 +1666,9 @@ parse_items (xmlNodePtr node, case GREETER_ITEM_TYPE_BUTTON: res = parse_gtkbutton (child, info, error); break; + case GREETER_ITEM_TYPE_COMBO_BOX_ENTRY: + res = parse_combo_box_entry (child, info, error); + break; default: g_set_error (error, GREETER_PARSER_ERROR,