Index: gdm-2.20.8/acconfig.h
===================================================================
--- gdm-2.20.8.orig/acconfig.h	2008-09-03 20:36:29.000000000 +0200
+++ gdm-2.20.8/acconfig.h	2009-01-28 15:16:44.000000000 +0100
@@ -5,6 +5,7 @@
 #undef REBOOT_COMMAND
 #undef SOUND_PROGRAM
 #undef SUSPEND_COMMAND
+#undef HIBERNATE_COMMAND
 #undef ENABLE_IPV6
 #undef ENABLE_NLS
 #undef ALWAYS_RESTART_SERVER
Index: gdm-2.20.8/config/gdm.conf.in
===================================================================
--- gdm-2.20.8.orig/config/gdm.conf.in	2008-09-03 20:36:09.000000000 +0200
+++ gdm-2.20.8/config/gdm.conf.in	2009-01-28 15:16:44.000000000 +0100
@@ -129,17 +129,18 @@
 RebootCommand=@REBOOT_COMMAND@
 HaltCommand=@HALT_COMMAND@
 SuspendCommand=@SUSPEND_COMMAND@
+HibernateCommand=@HIBERNATE_COMMAND@
 
 # The following options specify how GDM system commands are supported.
 #
 # Specify which actions are displayed in the greeter.  Valid values are HALT,
-# REBOOT, SUSPEND, and CUSTOM_CMD separated by semicolons.
-SystemCommandsInMenu=HALT;REBOOT;SUSPEND;CUSTOM_CMD
+# REBOOT, HIBERNATE, SUSPEND, and CUSTOM_CMD separated by semicolons.
+SystemCommandsInMenu=HALT;REBOOT;HIBERNATE;SUSPEND;CUSTOM_CMD
 
 # Specify which actions are supported by QUERY_LOGOUT_ACTION, SET_LOGOUT_ACTION
-# and SET_SAFE_LOGOUT_ACTION.  Valid values are HALT, REBOOT, SUSPEND, and
+# and SET_SAFE_LOGOUT_ACTION.  Valid values are HALT, REBOOT, HIBERNATE, SUSPEND, and
 # CUSTOM_CMD separated by semicolons.
-AllowLogoutActions=HALT;REBOOT;SUSPEND;CUSTOM_CMD
+AllowLogoutActions=HALT;REBOOT;HIBERNATE;SUSPEND;CUSTOM_CMD
 
 # This feature is only functional if GDM is compiled with RBAC (Role Based
 # Access Control) support.
Index: gdm-2.20.8/config/Makefile.am
===================================================================
--- gdm-2.20.8.orig/config/Makefile.am	2008-09-03 20:36:09.000000000 +0200
+++ gdm-2.20.8/config/Makefile.am	2009-01-28 15:16:44.000000000 +0100
@@ -61,6 +61,7 @@
 		-e 's,[@]REBOOT_COMMAND[@],$(REBOOT_COMMAND),g' \
 		-e 's,[@]SOUND_PROGRAM[@],$(SOUND_PROGRAM),g' \
 		-e 's,[@]SUSPEND_COMMAND[@],$(SUSPEND_COMMAND),g' \
+		-e 's,[@]HIBERNATE_COMMAND[@],$(HIBERNATE_COMMAND),g' \
 		-e 's,[@]XEVIE_OPTION[@],$(XEVIE_OPTION),g' \
 		-e 's,[@]ALWAYS_RESTART_SERVER[@],$(ALWAYS_RESTART_SERVER),g' \
 		-e 's,[@]UTMP_LINE_ATTACHED[@],$(UTMP_LINE_ATTACHED),g' \
Index: gdm-2.20.8/configure.ac
===================================================================
--- gdm-2.20.8.orig/configure.ac	2009-01-28 15:16:44.000000000 +0100
+++ gdm-2.20.8/configure.ac	2009-01-28 15:16:44.000000000 +0100
@@ -1090,6 +1090,7 @@
 	HOST_HALT_COMMAND="/usr/bin/poweroff;/sbin/poweroff;/sbin/shutdown -h now;/usr/sbin/shutdown -h now"
 	HOST_REBOOT_COMMAND="/usr/bin/reboot;/sbin/reboot;/sbin/shutdown -r now;/usr/sbin/shutdown -r now"
 	HOST_SUSPEND_COMMAND=""
+	HOST_HIBERNATE_COMMAND=""
 	HOST_XSESSION_SHELL=/bin/sh
 	HOST_SOUND_PROGRAM=/usr/bin/play
 	HOST_GDMGNOMESESSIONCMD=gnome-session
@@ -1106,6 +1107,7 @@
 test "x$HALT_COMMAND" == x && HALT_COMMAND=${HOST_HALT_COMMAND}
 test "x$REBOOT_COMMAND" == x && REBOOT_COMMAND=${HOST_REBOOT_COMMAND}
 test "x$SUSPEND_COMMAND" == x && SUSPEND_COMMAND=${HOST_SUSPEND_COMMAND}
+test "x$HIBERNATE_COMMAND" == x && HIBERNATE_COMMAND=${HOST_HIBERNATE_COMMAND}
 test "x$XSESSION_SHELL" == x && XSESSION_SHELL=${HOST_XSESSION_SHELL}
 test "x$SOUND_PROGRAM" == x && SOUND_PROGRAM=${HOST_SOUND_PROGRAM}
 test "x$GDMGNOMESESSIONCMD" == x && GDMGNOMESESSIONCMD=${HOST_GDMGNOMESESSIONCMD}
@@ -1313,6 +1315,8 @@
 AC_DEFINE_UNQUOTED(REBOOT_COMMAND,"$REBOOT_COMMAND")
 AC_SUBST(SUSPEND_COMMAND)
 AC_DEFINE_UNQUOTED(SUSPEND_COMMAND,"$SUSPEND_COMMAND")
+AC_SUBST(HIBERNATE_COMMAND)
+AC_DEFINE_UNQUOTED(HIBERNATE_COMMAND,"$HIBERNATE_COMMAND")
 AC_SUBST(XSESSION_SHELL)
 AC_DEFINE_UNQUOTED(XSESSION_SHELL,"$XSESSION_SHELL")
 AC_SUBST(GDM_USER_PATH)
Index: gdm-2.20.8/daemon/display.h
===================================================================
--- gdm-2.20.8.orig/daemon/display.h	2008-09-03 20:36:08.000000000 +0200
+++ gdm-2.20.8/daemon/display.h	2009-01-28 15:16:44.000000000 +0100
@@ -62,6 +62,7 @@
 	GDM_LOGOUT_ACTION_HALT,
 	GDM_LOGOUT_ACTION_REBOOT,
 	GDM_LOGOUT_ACTION_SUSPEND,
+	GDM_LOGOUT_ACTION_HIBERNATE,
 	GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST,
 	GDM_LOGOUT_ACTION_CUSTOM_CMD_LAST = GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + GDM_CUSTOM_COMMAND_MAX - 1,
 	GDM_LOGOUT_ACTION_LAST
Index: gdm-2.20.8/daemon/gdm.c
===================================================================
--- gdm-2.20.8.orig/daemon/gdm.c	2009-01-28 15:16:44.000000000 +0100
+++ gdm-2.20.8/daemon/gdm.c	2009-01-28 15:16:44.000000000 +0100
@@ -675,6 +675,22 @@
 	try_commands (suspend);
 }
 
+static void
+hibernate_machine (void)
+{
+	const gchar **hibernate;
+
+	hibernate = gdm_daemon_config_get_value_string_array (GDM_KEY_HIBERNATE);
+
+	gdm_info (_("Master hibernating..."));
+
+	if (hibernate == NULL) {
+		return;
+	}
+
+	try_commands (hibernate);
+}
+
 #ifdef __linux__
 static void
 change_to_first_and_clear (gboolean restart)
@@ -957,6 +973,7 @@
 	if (status == DISPLAY_RESTARTGDM ||
 	    status == DISPLAY_REBOOT     ||
 	    status == DISPLAY_SUSPEND    ||
+	    status == DISPLAY_HIBERNATE  ||
 	    status == DISPLAY_HALT) {
 		/*
 		 * Reset status to DISPLAY_REMANAGE if it is not valid to
@@ -966,13 +983,13 @@
 			GDM_KEY_SYSTEM_MENU, d->name);
 
 		if (!sysmenu) {
-			gdm_info (_("Restart GDM, Restart machine, Suspend, or Halt request when there is no system menu from display %s"), d->name);
+			gdm_info (_("Restart GDM, Restart machine, Suspend, Hibernate, or Halt request when there is no system menu from display %s"), d->name);
 			status = DISPLAY_REMANAGE;
 		}
 
 
 		if ( ! d->attached) {
-			gdm_info (_("Restart GDM, Restart machine, Suspend or Halt request from a non-static display %s"), d->name);
+			gdm_info (_("Restart GDM, Restart machine, Suspend Hibernate, or Halt request from a non-static display %s"), d->name);
 			status = DISPLAY_REMANAGE;
 		}
 
@@ -990,6 +1007,10 @@
 			if (gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) == NULL)
 				status = DISPLAY_REMANAGE;
 			break;
+		case DISPLAY_HIBERNATE:
+			if (gdm_daemon_config_get_value_string_array (GDM_KEY_HIBERNATE) == NULL)
+				status = DISPLAY_REMANAGE;
+			break;
 		default:
 			break;
 		}
@@ -1084,6 +1105,15 @@
 		goto start_autopsy;
 		break;
 
+	case DISPLAY_HIBERNATE:   /* Hibernate machine */
+		/* XXX: this is ugly, why should there be a hibernate like this,
+		 * see GDM_SOP_HIBERNATE_MACHINE */
+		hibernate_machine ();
+
+		status = DISPLAY_REMANAGE;
+		goto start_autopsy;
+		break;
+
 	case DISPLAY_RESTARTGDM:
 		gdm_restart_now ();
 		break;
@@ -1261,6 +1291,10 @@
 		suspend_machine ();
 		break;
 
+	case GDM_LOGOUT_ACTION_HIBERNATE:
+		hibernate_machine ();
+		break;
+
 	default:
 	        /* This is a bit ugly but its the only place we can
 		   check for the range of values */
@@ -2580,6 +2614,22 @@
 		if (sysmenu && gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) != NULL) {
 			suspend_machine ();
 		}
+	} else if (strncmp (msg, GDM_SOP_HIBERNATE_MACHINE " ",
+			    strlen (GDM_SOP_HIBERNATE_MACHINE " ")) == 0) {
+		GdmDisplay *d;
+		long slave_pid;
+		gboolean sysmenu;
+
+		if (sscanf (msg, GDM_SOP_HIBERNATE_MACHINE " %ld", &slave_pid) != 1)
+			return;
+		d = gdm_display_lookup (slave_pid);
+
+		gdm_info (_("Master hibernating..."));
+
+		sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name);
+		if (sysmenu && gdm_daemon_config_get_value_string_array (GDM_KEY_HIBERNATE) != NULL) {
+			hibernate_machine ();
+		}
 	} else if (strncmp (msg, GDM_SOP_CHOSEN_THEME " ",
 		            strlen (GDM_SOP_CHOSEN_THEME " ")) == 0) {
 		GdmDisplay *d;
@@ -3824,6 +3874,14 @@
 			g_string_append (reply, "!");
 		sep = ";";
 	}
+	if (gdm_daemon_config_get_value_string_array (GDM_KEY_HIBERNATE) &&
+	    is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HIBERNATE)) {
+		g_string_append_printf (reply, "%s%s", sep,
+			GDM_SUP_LOGOUT_ACTION_HIBERNATE);
+		if (logout_action == GDM_LOGOUT_ACTION_HIBERNATE)
+			g_string_append (reply, "!");
+		sep = ";";
+	}
 
 	if (is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) {
 		for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
@@ -4073,6 +4131,11 @@
 		   is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) {
 		disp->logout_action = GDM_LOGOUT_ACTION_SUSPEND;
 		was_ok = TRUE;
+	} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HIBERNATE) == 0 &&
+		   gdm_daemon_config_get_value_string_array (GDM_KEY_HIBERNATE) &&
+		   is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HIBERNATE)) {
+		disp->logout_action = GDM_LOGOUT_ACTION_HIBERNATE;
+		was_ok = TRUE;
 	}
 	else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE,
 			  strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0 &&
@@ -4141,6 +4204,11 @@
 		   is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) {
 		safe_logout_action = GDM_LOGOUT_ACTION_SUSPEND;
 		was_ok = TRUE;
+	} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HIBERNATE) == 0 &&
+		   gdm_daemon_config_get_value_string_array (GDM_KEY_HIBERNATE) &&
+		   is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HIBERNATE)) {
+		safe_logout_action = GDM_LOGOUT_ACTION_HIBERNATE;
+		was_ok = TRUE;
 	}
 	else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE,
 			  strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0 &&
Index: gdm-2.20.8/daemon/gdm-daemon-config.c
===================================================================
--- gdm-2.20.8.orig/daemon/gdm-daemon-config.c	2008-09-03 20:36:08.000000000 +0200
+++ gdm-2.20.8/daemon/gdm-daemon-config.c	2009-01-28 15:16:44.000000000 +0100
@@ -1732,6 +1732,7 @@
         case GDM_ID_HALT:
         case GDM_ID_REBOOT:
         case GDM_ID_SUSPEND:
+        case GDM_ID_HIBERNATE:
 		res = validate_power_action (config, source, value);
 		break;
         case GDM_ID_STANDARD_XSERVER:
Index: gdm-2.20.8/daemon/gdm-daemon-config-entries.h
===================================================================
--- gdm-2.20.8.orig/daemon/gdm-daemon-config-entries.h	2008-09-03 20:36:08.000000000 +0200
+++ gdm-2.20.8/daemon/gdm-daemon-config-entries.h	2009-01-28 15:16:44.000000000 +0100
@@ -78,6 +78,7 @@
 	GDM_ID_BASE_XSESSION,
 	GDM_ID_DEFAULT_SESSION,
 	GDM_ID_SUSPEND,
+	GDM_ID_HIBERNATE,
 	GDM_ID_USER_AUTHDIR,
 	GDM_ID_USER_AUTHDIR_FALLBACK,
 	GDM_ID_USER_AUTHFILE,
@@ -305,6 +306,7 @@
 	{ GDM_CONFIG_GROUP_DAEMON, "HaltCommand", GDM_CONFIG_VALUE_STRING_ARRAY, HALT_COMMAND, GDM_ID_HALT },
 	{ GDM_CONFIG_GROUP_DAEMON, "RebootCommand", GDM_CONFIG_VALUE_STRING_ARRAY, REBOOT_COMMAND, GDM_ID_REBOOT },
 	{ GDM_CONFIG_GROUP_DAEMON, "SuspendCommand", GDM_CONFIG_VALUE_STRING_ARRAY, SUSPEND_COMMAND, GDM_ID_SUSPEND },
+	{ GDM_CONFIG_GROUP_DAEMON, "HibernateCommand", GDM_CONFIG_VALUE_STRING_ARRAY, HIBERNATE_COMMAND, GDM_ID_HIBERNATE },
 
 	{ GDM_CONFIG_GROUP_DAEMON, "DisplayInitDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/Init", GDM_ID_DISPLAY_INIT_DIR },
 	{ GDM_CONFIG_GROUP_DAEMON, "KillInitClients", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_KILL_INIT_CLIENTS },
@@ -352,8 +354,8 @@
 	/* How long to wait before assuming an Xserver has timed out */
 	{ GDM_CONFIG_GROUP_DAEMON, "GdmXserverTimeout", GDM_CONFIG_VALUE_INT, "10", GDM_ID_XSERVER_TIMEOUT },
 
-	{ GDM_CONFIG_GROUP_DAEMON, "SystemCommandsInMenu", GDM_CONFIG_VALUE_STRING_ARRAY, "HALT;REBOOT;SUSPEND;CUSTOM_CMD", GDM_ID_SYSTEM_COMMANDS_IN_MENU },
-	{ GDM_CONFIG_GROUP_DAEMON, "AllowLogoutActions", GDM_CONFIG_VALUE_STRING_ARRAY, "HALT;REBOOT;SUSPEND;CUSTOM_CMD", GDM_ID_ALLOW_LOGOUT_ACTIONS },
+	{ GDM_CONFIG_GROUP_DAEMON, "SystemCommandsInMenu", GDM_CONFIG_VALUE_STRING_ARRAY, "HALT;REBOOT;SUSPEND;HIBERNATE;CUSTOM_CMD", GDM_ID_SYSTEM_COMMANDS_IN_MENU },
+	{ GDM_CONFIG_GROUP_DAEMON, "AllowLogoutActions", GDM_CONFIG_VALUE_STRING_ARRAY, "HALT;REBOOT;SUSPEND;HIBERNATE;CUSTOM_CMD", GDM_ID_ALLOW_LOGOUT_ACTIONS },
 	{ GDM_CONFIG_GROUP_DAEMON, "RBACSystemCommandKeys", GDM_CONFIG_VALUE_STRING_ARRAY, GDM_RBAC_SYSCMD_KEYS, GDM_ID_RBAC_SYSTEM_COMMAND_KEYS },
 
 	{ GDM_CONFIG_GROUP_SECURITY, "AllowRoot", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALLOW_ROOT },
Index: gdm-2.20.8/daemon/gdm-daemon-config-keys.h
===================================================================
--- gdm-2.20.8.orig/daemon/gdm-daemon-config-keys.h	2009-01-28 15:16:44.000000000 +0100
+++ gdm-2.20.8/daemon/gdm-daemon-config-keys.h	2009-01-28 15:16:44.000000000 +0100
@@ -78,6 +78,7 @@
 #define GDM_KEY_BASE_XSESSION "daemon/BaseXsession=" GDMCONFDIR "/Xsession"
 #define GDM_KEY_DEFAULT_SESSION "daemon/DefaultSession=gnome.desktop"
 #define GDM_KEY_SUSPEND "daemon/SuspendCommand=" SUSPEND_COMMAND
+#define GDM_KEY_HIBERNATE "daemon/HibernateCommand=" HIBERNATE_COMMAND
 #define GDM_KEY_USER_AUTHDIR "daemon/UserAuthDir="
 #define GDM_KEY_USER_AUTHDIR_FALLBACK "daemon/UserAuthFBDir=/tmp"
 #define GDM_KEY_USER_AUTHFILE "daemon/UserAuthFile=.Xauthority"
@@ -99,8 +100,8 @@
 #define GDM_KEY_VT_ALLOCATION "daemon/VTAllocation=true"
 #define GDM_KEY_CONSOLE_CANNOT_HANDLE "daemon/ConsoleCannotHandle=am,ar,az,bn,el,fa,gu,hi,ja,ko,ml,mr,pa,ta,zh"
 #define GDM_KEY_XSERVER_TIMEOUT "daemon/GdmXserverTimeout=10"
-#define GDM_KEY_SYSTEM_COMMANDS_IN_MENU "daemon/SystemCommandsInMenu=HALT;REBOOT;SUSPEND;CUSTOM_CMD"
-#define GDM_KEY_ALLOW_LOGOUT_ACTIONS "daemon/AllowLogoutActions=HALT;REBOOT;SUSPEND;CUSTOM_CMD"
+#define GDM_KEY_SYSTEM_COMMANDS_IN_MENU "daemon/SystemCommandsInMenu=HALT;REBOOT;SUSPEND;HIBERNATE;CUSTOM_CMD"
+#define GDM_KEY_ALLOW_LOGOUT_ACTIONS "daemon/AllowLogoutActions=HALT;REBOOT;SUSPEND;HIBERNATE;CUSTOM_CMD"
 #define GDM_KEY_RBAC_SYSTEM_COMMAND_KEYS "daemon/RBACSystemCommandKeys=" GDM_RBAC_SYSCMD_KEYS
 
 #define GDM_KEY_SERVER_PREFIX "server-"
Index: gdm-2.20.8/daemon/gdm.h
===================================================================
--- gdm-2.20.8.orig/daemon/gdm.h	2008-09-03 20:36:08.000000000 +0200
+++ gdm-2.20.8/daemon/gdm.h	2009-01-28 15:16:44.000000000 +0100
@@ -33,6 +33,7 @@
 #define DISPLAY_REBOOT 8	/* Rebewt */
 #define DISPLAY_HALT 16		/* Halt */
 #define DISPLAY_SUSPEND 17	/* Suspend (don't use, use the interrupt) */
+#define DISPLAY_HIBERNATE 18
 #define DISPLAY_CHOSEN 20	/* successful chooser session,
 				   restart display */
 #define DISPLAY_RUN_CHOOSER 30	/* Run chooser */
Index: gdm-2.20.8/daemon/gdm-socket-protocol.h
===================================================================
--- gdm-2.20.8.orig/daemon/gdm-socket-protocol.h	2008-09-03 20:36:08.000000000 +0200
+++ gdm-2.20.8/daemon/gdm-socket-protocol.h	2009-01-28 15:16:44.000000000 +0100
@@ -69,6 +69,7 @@
 #define GDM_INTERRUPT_TIMED_LOGIN 'T'
 #define GDM_INTERRUPT_CONFIGURE   'C'
 #define GDM_INTERRUPT_SUSPEND     'S'
+#define GDM_INTERRUPT_HIBERNATE   'I'
 #define GDM_INTERRUPT_SELECT_USER 'U'
 #define GDM_INTERRUPT_LOGIN_SOUND 'L'
 #define GDM_INTERRUPT_THEME       'H'
@@ -142,6 +143,7 @@
 #define GDM_SOP_SOFT_RESTART_SERVERS "SOFT_RESTART_SERVERS"  /* no arguments */
 /* Suspend the machine if it is even allowed */
 #define GDM_SOP_SUSPEND_MACHINE "SUSPEND_MACHINE"  /* no arguments */
+#define GDM_SOP_HIBERNATE_MACHINE "HIBERNATE_MACHINE"  /* no arguments */
 #define GDM_SOP_CHOSEN_THEME "CHOSEN_THEME"  /* <slave pid> <theme name> */
 
 /*Execute custom cmd*/
@@ -230,6 +232,7 @@
 #define GDM_SUP_LOGOUT_ACTION_HALT	          "HALT"
 #define GDM_SUP_LOGOUT_ACTION_REBOOT	          "REBOOT"
 #define GDM_SUP_LOGOUT_ACTION_SUSPEND	          "SUSPEND"
+#define GDM_SUP_LOGOUT_ACTION_HIBERNATE        "HIBERNATE"
 #define GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "CUSTOM_CMD"
 #define GDM_SUP_QUERY_VT "QUERY_VT"
 #define GDM_SUP_SET_VT "SET_VT"
Index: gdm-2.20.8/daemon/Makefile.in
===================================================================
--- gdm-2.20.8.orig/daemon/Makefile.in	2008-09-03 20:49:51.000000000 +0200
+++ gdm-2.20.8/daemon/Makefile.in	2009-01-28 15:16:44.000000000 +0100
@@ -272,6 +272,7 @@
 SSHDESKTOP = @SSHDESKTOP@
 STRIP = @STRIP@
 SUSPEND_COMMAND = @SUSPEND_COMMAND@
+HIBERNATE_COMMAND = @HIBERNATE_COMMAND@
 SYSCONFDIR = @SYSCONFDIR@
 USE_NLS = @USE_NLS@
 UTILS_CFLAGS = @UTILS_CFLAGS@
Index: gdm-2.20.8/daemon/slave.c
===================================================================
--- gdm-2.20.8.orig/daemon/slave.c	2009-01-28 15:16:44.000000000 +0100
+++ gdm-2.20.8/daemon/slave.c	2009-01-28 15:16:44.000000000 +0100
@@ -5243,6 +5243,7 @@
 			     WEXITSTATUS (status) == DISPLAY_REBOOT ||
 			     WEXITSTATUS (status) == DISPLAY_HALT ||
 			     WEXITSTATUS (status) == DISPLAY_SUSPEND ||
+			     WEXITSTATUS (status) == DISPLAY_HIBERNATE ||
 			     WEXITSTATUS (status) == DISPLAY_RUN_CHOOSER ||
 			     WEXITSTATUS (status) == DISPLAY_RESTARTGDM ||
 			     WEXITSTATUS (status) == DISPLAY_GREETERFAILED)) {
@@ -5520,6 +5521,20 @@
 			/* Not interrupted, continue reading input,
 			 * just proxy this to the master server */
 			return TRUE;
+		case GDM_INTERRUPT_HIBERNATE:
+			if (d->attached &&
+			    gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name) &&
+			    ! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_HIBERNATE))) {
+			    	gchar *msg = g_strdup_printf ("%s %ld", 
+					GDM_SOP_HIBERNATE_MACHINE,
+					(long)getpid ());
+
+				gdm_slave_send (msg, FALSE /* wait_for_ack */);
+				g_free (msg);
+			}
+			/* Not interrupted, continue reading input,
+			 * just proxy this to the master server */
+			return TRUE;
 		case GDM_INTERRUPT_LOGIN_SOUND:
 			if (d->attached &&
 			    ! play_login_sound (gdm_daemon_config_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FILE))) {
Index: gdm-2.20.8/gui/gdmlogin.c
===================================================================
--- gdm-2.20.8.orig/gui/gdmlogin.c	2008-09-03 20:35:57.000000000 +0200
+++ gdm-2.20.8/gui/gdmlogin.c	2009-01-28 15:16:44.000000000 +0100
@@ -72,6 +72,7 @@
 gboolean GdmConfiguratorFound               = FALSE;
 gboolean *GdmCustomCmdsFound                = NULL;
 gboolean GdmSuspendFound                    = FALSE;
+gboolean GdmHibernateFound                  = FALSE;
 gboolean GdmHaltFound                       = FALSE;
 gboolean GdmRebootFound                     = FALSE;
 gboolean GdmAnyCustomCmdsFound              = FALSE;
@@ -751,6 +752,19 @@
 }
 
 static void
+gdm_login_hibernate_handler (void)
+{
+	if (gdm_wm_warn_dialog (
+	    _("Are you sure you want to hibernate the computer?"), "",
+	    _("_Hibernate"), NULL, TRUE) == GTK_RESPONSE_YES) {
+
+		/* hibernate interruption */
+		printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_HIBERNATE);
+		fflush (stdout);
+	}
+}
+
+static void
 gdm_theme_handler (GtkWidget *widget, gpointer data)
 {
     const char *theme_name = (const char *)data;
@@ -2306,6 +2320,17 @@
 		gtk_widget_show (GTK_WIDGET (item));
 		got_anything = TRUE;
 	}
+
+	if (gdm_working_command_exists (gdm_config_get_string (GDM_KEY_HIBERNATE)) &&
+	    gdm_common_is_action_available ("HIBERNATE")) {
+		item = gtk_menu_item_new_with_mnemonic (_("_Hibernate"));
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+		g_signal_connect (G_OBJECT (item), "activate",
+				  G_CALLBACK (gdm_login_hibernate_handler), 
+				  NULL);
+		gtk_widget_show (GTK_WIDGET (item));
+		got_anything = TRUE;
+	}
 	
 	if (gdm_common_is_action_available ("CUSTOM_CMD")) {
 		for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {			
@@ -2877,6 +2902,7 @@
 	gdm_config_get_string (GDM_KEY_SOUND_PROGRAM);
 	gdm_config_get_string (GDM_KEY_SOUND_ON_LOGIN_FILE);
 	gdm_config_get_string (GDM_KEY_SUSPEND);
+	gdm_config_get_string (GDM_KEY_HIBERNATE);
 	gdm_config_get_string (GDM_KEY_TIMED_LOGIN);
 	gdm_config_get_string (GDM_KEY_USE_24_CLOCK);
 	gdm_config_get_string (GDM_KEY_WELCOME);
@@ -2992,6 +3018,7 @@
 	    gdm_config_reload_string (GDM_KEY_REBOOT) ||
 	    gdm_config_reload_string (GDM_KEY_SESSION_DESKTOP_DIR) ||
 	    gdm_config_reload_string (GDM_KEY_SUSPEND) ||
+	    gdm_config_reload_string (GDM_KEY_HIBERNATE) ||
 	    gdm_config_reload_string (GDM_KEY_TIMED_LOGIN) ||
 	    gdm_config_reload_string (GDM_KEY_RBAC_SYSTEM_COMMAND_KEYS) ||
 	    gdm_config_reload_string (GDM_KEY_SYSTEM_COMMANDS_IN_MENU) ||
Index: gdm-2.20.8/gui/gdmsetup.c
===================================================================
--- gdm-2.20.8.orig/gui/gdmsetup.c	2008-09-03 20:35:57.000000000 +0200
+++ gdm-2.20.8/gui/gdmsetup.c	2009-01-28 15:16:44.000000000 +0100
@@ -147,6 +147,7 @@
 	HALT_CMD,
 	REBOOT_CMD,
 	SUSPEND_CMD,
+	HIBERNATE_CMD,
 	CUSTOM_CMD
 };
 
@@ -1581,6 +1582,11 @@
 			gtk_entry_set_text (GTK_ENTRY (hrs_cmd_entry), ve_sure_string (val));
 			enabled_command = !ve_string_empty (val);
 		}
+		else if (selected == HIBERNATE_CMD) {
+			val = gdm_config_get_string (GDM_KEY_HIBERNATE);			
+			gtk_entry_set_text (GTK_ENTRY (hrs_cmd_entry), ve_sure_string (val));
+			enabled_command = !ve_string_empty (val);
+		}
 		else {
 			gchar *key_string = NULL;
 
@@ -2039,7 +2045,7 @@
 
 		hrs_cmd_vbox = glade_xml_get_widget (xml_commands, "hrs_command_vbox");
 		custom_cmd_vbox = glade_xml_get_widget (xml_commands, "custom_command_vbox");
-		if (selected > SUSPEND_CMD) {
+		if (selected > HIBERNATE_CMD) {
 			/* We are dealing with custom commands */							
 			gtk_widget_show (custom_cmd_vbox);
 			gtk_widget_hide (hrs_cmd_vbox);					
@@ -2323,7 +2329,9 @@
 		else if (selected == REBOOT_CMD)
 			cmd_key = g_strdup (GDM_KEY_REBOOT);
 		else if (selected == SUSPEND_CMD)
-			cmd_key = g_strdup (GDM_KEY_SUSPEND);
+			cmd_key = g_strdup (GDM_KEY_SUSPEND); 
+		else if (selected == HIBERNATE_CMD)
+			cmd_key = g_strdup (GDM_KEY_HIBERNATE); 
 		
 		old_val = gdm_config_get_string (cmd_key);		
 			
@@ -3650,6 +3658,8 @@
 		value = gdm_config_get_string (GDM_KEY_REBOOT);		
 	else if (selected == SUSPEND_CMD) 
 		value = gdm_config_get_string (GDM_KEY_SUSPEND);
+	else if (selected == HIBERNATE_CMD) 
+		value = gdm_config_get_string (GDM_KEY_HIBERNATE);
 	else {
 		gchar *key_string;
 		gint i;
@@ -3890,6 +3900,7 @@
 		gtk_combo_box_append_text (GTK_COMBO_BOX (command_chooser), _("Halt command"));
 		gtk_combo_box_append_text (GTK_COMBO_BOX (command_chooser), _("Reboot command"));
 		gtk_combo_box_append_text (GTK_COMBO_BOX (command_chooser), _("Suspend command"));
+		gtk_combo_box_append_text (GTK_COMBO_BOX (command_chooser), _("Hibernate command"));
 		
 		/* Add all the custom commands */
 		for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
Index: gdm-2.20.8/gui/greeter/greeter.c
===================================================================
--- gdm-2.20.8.orig/gui/greeter/greeter.c	2008-09-03 20:35:57.000000000 +0200
+++ gdm-2.20.8/gui/greeter/greeter.c	2009-01-28 15:16:44.000000000 +0100
@@ -75,6 +75,7 @@
 gboolean *GdmCustomCmdsFound   = NULL;
 gboolean GdmAnyCustomCmdsFound = FALSE;
 gboolean GdmSuspendFound       = FALSE;
+gboolean GdmHibernateFound       = FALSE;
 gboolean GdmConfiguratorFound  = FALSE;
 
 /* FIXME: hack */
@@ -888,6 +889,7 @@
 	gdm_config_get_string (GDM_KEY_HALT);
 	gdm_config_get_string (GDM_KEY_REBOOT);
 	gdm_config_get_string (GDM_KEY_SUSPEND);
+	gdm_config_get_string (GDM_KEY_HIBERNATE);
 	gdm_config_get_string (GDM_KEY_CONFIGURATOR);
 	gdm_config_get_string (GDM_KEY_INFO_MSG_FILE);
 	gdm_config_get_string (GDM_KEY_INFO_MSG_FONT);
@@ -984,6 +986,7 @@
 	    gdm_config_reload_string (GDM_KEY_HALT) ||
 	    gdm_config_reload_string (GDM_KEY_REBOOT) ||
 	    gdm_config_reload_string (GDM_KEY_SUSPEND) ||
+	    gdm_config_reload_string (GDM_KEY_HIBERNATE) ||
 	    gdm_config_reload_string (GDM_KEY_CONFIGURATOR) ||
 	    gdm_config_reload_string (GDM_KEY_INFO_MSG_FILE) ||
 	    gdm_config_reload_string (GDM_KEY_INFO_MSG_FONT) ||
@@ -1385,6 +1388,7 @@
   GdmHaltFound            = gdm_working_command_exists (gdm_config_get_string (GDM_KEY_HALT));
   GdmRebootFound          = gdm_working_command_exists (gdm_config_get_string (GDM_KEY_REBOOT));
   GdmSuspendFound         = gdm_working_command_exists (gdm_config_get_string (GDM_KEY_SUSPEND));
+  GdmHibernateFound    = gdm_working_command_exists (gdm_config_get_string (GDM_KEY_HIBERNATE));
   GdmConfiguratorFound    = gdm_working_command_exists (gdm_config_get_string (GDM_KEY_CONFIGURATOR));
 
   GdmCustomCmdsFound = g_new0 (gboolean, GDM_CUSTOM_COMMAND_MAX);
Index: gdm-2.20.8/gui/greeter/greeter_configuration.h
===================================================================
--- gdm-2.20.8.orig/gui/greeter/greeter_configuration.h	2009-01-28 15:16:44.000000000 +0100
+++ gdm-2.20.8/gui/greeter/greeter_configuration.h	2009-01-28 15:16:44.000000000 +0100
@@ -31,6 +31,7 @@
 extern gchar *GdmHalt;
 extern gchar *GdmReboot;
 extern gchar *GdmSuspend;
+extern gchar *GdmHibernate;
 extern gchar *GdmConfigurator;
 extern gboolean GdmHaltFound;
 extern gboolean GdmRebootFound;
@@ -38,6 +39,7 @@
 extern gboolean *GdmCustomCmdsFound;
 extern gboolean GdmAnyCustomCmdsFound;
 extern gboolean GdmSuspendFound;
+extern gboolean GdmHibernateFound;
 extern gboolean GdmConfiguratorFound;
 extern gchar *GdmSessionDir;
 extern gchar *GdmDefaultSession;
Index: gdm-2.20.8/gui/greeter/greeter_item.c
===================================================================
--- gdm-2.20.8.orig/gui/greeter/greeter_item.c	2008-09-03 20:35:57.000000000 +0200
+++ gdm-2.20.8/gui/greeter/greeter_item.c	2009-01-28 15:16:44.000000000 +0100
@@ -226,6 +226,10 @@
       (info->show_type != NULL &&
        strcmp (info->show_type, "suspend") == 0))
 	  return FALSE;
+  if (( ! sysmenu || ! GdmHibernateFound) &&
+      (info->show_type != NULL &&
+       strcmp (info->show_type, "hibernate") == 0))
+	  return FALSE;
 
   if (info->show_type != NULL && 
       sscanf (info->show_type, "custom_cmd%d", &i) == 1 &&
Index: gdm-2.20.8/gui/greeter/greeter_system.c
===================================================================
--- gdm-2.20.8.orig/gui/greeter/greeter_system.c	2008-09-03 20:35:57.000000000 +0200
+++ gdm-2.20.8/gui/greeter/greeter_system.c	2009-01-28 15:16:44.000000000 +0100
@@ -47,6 +47,7 @@
 extern gboolean *GdmCustomCmdsFound;
 extern gboolean  GdmAnyCustomCmdsFound;
 extern gboolean  GdmSuspendFound;
+extern gboolean  GdmHibernateFound;
 extern gboolean  GdmConfiguratorFound;
 
 /* doesn't check for executability, just for existance */
@@ -119,6 +120,17 @@
 }
 
 static void
+query_greeter_hibernate_handler (void)
+{
+	if (gdm_wm_warn_dialog (_("Are you sure you want to hibernate the computer?"), "",
+			     _("_Hibernate"), NULL, TRUE) == GTK_RESPONSE_YES) {
+		/* hibernate interruption */
+		printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_HIBERNATE);
+		fflush (stdout);
+	}
+}
+
+static void
 greeter_restart_handler (void)
 {
 	_exit (DISPLAY_REBOOT);
@@ -144,6 +156,15 @@
 	fflush (stdout);
 }
 
+
+static void
+greeter_hibernate_handler (void)
+{
+       printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_HIBERNATE);
+       fflush (stdout);
+}
+
+
 static void
 greeter_config_handler (void)
 {
@@ -207,7 +228,7 @@
 				  NULL);
 	}
 
-	if (GdmRebootFound || GdmHaltFound || GdmSuspendFound || GdmAnyCustomCmdsFound) {
+	if (GdmRebootFound || GdmHaltFound || GdmSuspendFound  || GdmHibernateFound || GdmAnyCustomCmdsFound) {
 		sep = gtk_separator_menu_item_new ();
 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), sep);
 		gtk_widget_show (sep);
@@ -246,6 +267,18 @@
 				  NULL);
 	}
 
+	if (GdmHibernateFound && gdm_common_is_action_available ("HIBERNATE")) {
+		w = gtk_image_menu_item_new_with_mnemonic (_("_Hibernate"));
+ 		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (w),
+ 					       gtk_image_new_from_icon_name ("system-hibernate", GTK_ICON_SIZE_MENU));
+
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), w);
+		gtk_widget_show (GTK_WIDGET (w));
+		g_signal_connect (G_OBJECT (w), "activate",
+				  G_CALLBACK (query_greeter_hibernate_handler),
+				  NULL);
+	}
+
 	if (GdmAnyCustomCmdsFound &&
 	    gdm_common_is_action_available ("CUSTOM_CMD")) {
 		for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
@@ -290,6 +323,7 @@
   GtkWidget *group_radio = NULL;
   GtkWidget *halt_radio = NULL;
   GtkWidget *suspend_radio = NULL;
+  GtkWidget *hibernate_radio = NULL;
   GtkWidget *restart_radio = NULL;
   GtkWidget **custom_cmds_radio = NULL;
   GtkWidget *config_radio = NULL;
@@ -421,6 +455,23 @@
 	  gtk_widget_show (suspend_radio);
   }
 
+  if (GdmHibernateFound) {
+	  if (group_radio != NULL)
+		  radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (group_radio));
+	  hibernate_radio = gtk_radio_button_new_with_mnemonic (radio_group,
+							      _("_Hibernate the computer"));
+	  group_radio = hibernate_radio;
+	  gtk_tooltips_set_tip (tooltips, GTK_WIDGET (hibernate_radio),
+				_("Hibernate your computer"),
+				NULL);
+	  g_signal_connect (G_OBJECT(hibernate_radio), "button_press_event",
+			    G_CALLBACK(radio_button_press_event), NULL);
+	  gtk_box_pack_start (GTK_BOX (vbox),
+			      hibernate_radio,
+			      FALSE, FALSE, 4);
+	  gtk_widget_show (hibernate_radio);
+  }
+
   if (gdm_config_get_bool (GDM_KEY_CHOOSER_BUTTON)) {
 	  if (group_radio != NULL)
 		  radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (group_radio));
@@ -494,6 +545,8 @@
     greeter_restart_handler ();
   else if (suspend_radio != NULL && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (suspend_radio)))
     greeter_suspend_handler ();
+  else if (hibernate_radio != NULL && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (hibernate_radio)))
+    greeter_hibernate_handler ();
   else if (config_radio != NULL && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (config_radio)))
     greeter_config_handler ();
   else if (chooser_radio != NULL && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (chooser_radio)))
@@ -522,6 +575,9 @@
   greeter_item_register_action_callback ("suspend_button",
 					 (ActionFunc)query_greeter_suspend_handler,
 					 NULL);
+  greeter_item_register_action_callback ("hibernate_button",
+					 (ActionFunc)query_greeter_hibernate_handler,
+					 NULL);
   greeter_item_register_action_callback ("system_button",
 					 (ActionFunc)greeter_system_handler,
 					 NULL);
Index: gdm-2.20.8/pixmaps/24x24/Makefile.am
===================================================================
--- gdm-2.20.8.orig/pixmaps/24x24/Makefile.am	2008-09-03 20:35:54.000000000 +0200
+++ gdm-2.20.8/pixmaps/24x24/Makefile.am	2009-01-28 15:16:44.000000000 +0100
@@ -3,6 +3,7 @@
 icons = \
 	preferences-desktop-locale.png \
 	preferences-desktop-remote-desktop.png \
+        system-hibernate.png \
 	system-log-out.png \
 	system-restart.png \
 	system-shut-down.png \
@@ -12,6 +13,7 @@
 icon_names = \
 	preferences_desktop_locale_24 $(srcdir)/preferences-desktop-locale.png \
 	preferences_desktop_remote_desktop_24 $(srcdir)/preferences-desktop-remote-desktop.png \
+        system_hibernate_24 $(srcdir)/system-hibernate.png \
 	system_log_out_24 $(srcdir)/system-log-out.png \
 	system_restart_24 $(srcdir)/system-restart.png \
 	system_shut_down_24 $(srcdir)/system-shut-down.png \
Index: gdm-2.20.8/pixmaps/24x24/system-hibernate.png.uue
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdm-2.20.8/pixmaps/24x24/system-hibernate.png.uue	2009-01-28 15:16:44.000000000 +0100
@@ -0,0 +1,30 @@
+begin 644 system-hibernate.png.uue
+MB5!.1PT*&@H````-24A$4@```!@````8"`8```#@=SWX`````7-21T(`KLX<
+MZ0````9B2T=$`/\`_P#_H+VGDP````EP2%ES```+$P``"Q,!`)J<&`````=T
+M24U%!]@"%@L+./JHX74```0\241!5$C'K9;?;Q15%,<_,SNSM3]"VD!+4@+$
+MA7;==0L!(C\J74B@;^*#E%;\`Y1(T,00$HP&'HQ/ONB3&N"%1/P1$BH0>/#!
+MA%!"(35-:RD5BA"J]`?==MOMW)D[]XX/XTY9J#51;C(/WWM^?.^YY]QSQECZ
+M2DT]\#:P#TCS?-8`\`/PM16HX$#%BO*/-[=LH?GE5UFS?`V5997_R6O!+7!W
+M]"Y=OUY-=U^Y?FQNQ#$M,VYVK$RN)+TZC67&N#_^^X+&.M`EV#3,!?4L,T9Z
+M=9H_Q_[@M_$['989-QNKEU2CM&(B/['H"=N;.P#XONN[1?645E0OJ<:,FXV6
+M81K85AQ?^?C*7]0P49L`P)7NOUZ7;<4Q3`,3H.`4D+Z,/N$)A"?8M6XWQ]J.
+M1[BXBOA8VW%VK=L=X2=]%)Q">&4`TO<HB-DP/*60RN>]U]XG59\"8&IVJN1T
+M3^+MC=M96K64+RY\CAVSB,5B%'T"802.$#S.3_(X/\EH;HPWFO>2JD_A:\61
+MTX>9S$\RF9^,G!;QD=.'\;4B59_BC>:]C.;&(C^.$/,$GO28GIEF*I\C49^@
+M-=,*P*$3!^D?[D>X@IE"/B*8*>01KJ!_N)]#)PX"T)II)5&?8"J?8WIF&D\^
+M$8%2/H[K,%.8)9O9`4!G3R>#]P;QE<)QG>A$Q8@=U\%7BL%[@W3V=`*0S>Q@
+MIC"+XSJHOPO&+-Z[ZPH<,4<VF07@8O<%/.GANB*2S1/,1?N>]+C8?2$D2&8C
+MF5)J/LE**80KD%)&K_AFWPULV\;W99@T*2,"S_,(@B#"-_MN`%!95AG)GB$`
+MD&+>B2]+WX04DMX'O<_H/:U;E)40:*D)=(!R->.S$]16+2.Y-LFM@5N8\;`E
+M:#^@_8-]H5&E%3G5GB:5#LMY?'8"Y6J,F$^@@OD<!"I`>YK`UW0-706@+=N.
+M$@KM:;2G,0RPJRSL*@O#(-I70M&6;0>@:^@J@1_NEQ`4EV&9G+IT$H".K1TT
+M9!I00OUSSQ&*ADP#'5O#'G7JTDD,J[0)EB#3,ACJNQV5W=FCYVAL2H:1^/-)
+MU7Z`$HK&IB1GCYZ+RGJH[S:F9900&,MWU@85*\I+C>=\OOGL6S:NW@C`F6MG
+M.'_M1WI[PR2O7[^>/=M>9_^V_0#TW._AK<-O$JNP2@CF1IR0H"Y=5UH5OL3S
+M/#YYYU/V;-BS:-<\_\MY/OKJ0^+Q.)9EE\C&!L9"@DQ+AIAI/M73-8[KL.FE
+M36Q/M[!Y[19JJY9%U=)]YSK7!KOH'NBFO*Q\0?O^*_T8=2W+[C;M;$JD7UQX
+M'+O2#9^^5F@=3C73-(F9,<K+RBFSRQ8>RO<&Z/NY;]CRIN3ED4</WTVN:J2N
+M9CEVS/Y?TUXJR5ANE)%'#_&FY&7#7F)MJ%Q5<2!>$]]MQ(S$\_BE"%0P[.6\
+JGPH/YKXT`!NH!6J`%Y[3;XL`<L#X7TKG82!+O,(?`````$E%3D2N0F""
+`
+end
Index: gdm-2.20.8/gui/gdmcommon.c
===================================================================
--- gdm-2.20.8.orig/gui/gdmcommon.c	2008-09-03 20:35:57.000000000 +0200
+++ gdm-2.20.8/gui/gdmcommon.c	2009-01-28 15:16:44.000000000 +0100
@@ -221,6 +221,7 @@
 	{
 		{"preferences-desktop-locale", 24, preferences_desktop_locale_24},
 		{"preferences-desktop-remote-desktop", 24, preferences_desktop_remote_desktop_24},
+		{"system-hibernate", 24, system_hibernate_24},
 		{"system-log-out", 24, system_log_out_24},
 		{"system-restart", 24, system_restart_24},
 		{"system-shut-down", 24, system_shut_down_24},
Index: gdm-2.20.8/config.h.in
===================================================================
--- gdm-2.20.8.orig/config.h.in	2008-09-03 20:49:50.000000000 +0200
+++ gdm-2.20.8/config.h.in	2009-01-28 15:16:44.000000000 +0100
@@ -6,6 +6,7 @@
 #undef REBOOT_COMMAND
 #undef SOUND_PROGRAM
 #undef SUSPEND_COMMAND
+#undef HIBERNATE_COMMAND
 #undef ENABLE_IPV6
 #undef ENABLE_NLS
 #undef ALWAYS_RESTART_SERVER
Index: gdm-2.20.8/gui/gdmgreeter.c
===================================================================
--- gdm-2.20.8.orig/gui/gdmgreeter.c	2009-01-28 15:16:50.000000000 +0100
+++ gdm-2.20.8/gui/gdmgreeter.c	2009-01-28 15:16:53.000000000 +0100
@@ -102,6 +102,18 @@
 #endif
 	g_strfreev (allowsyscmd);
 
+	if (ret == TRUE && strcmp(action, "HIBERNATE") == 0) {
+		/* Check if swap partitions are loaded.  Only allow hibernate
+                   if one is available. */
+		gchar *contents;
+		if (g_file_get_contents("/proc/swaps", &contents, NULL, NULL)) {
+			gchar *first_endl = strchr(contents, '\n');
+			if (!first_endl || first_endl[1] == '\0')
+				ret = FALSE;
+			g_free(contents);
+		}
+	}
+
 	return ret;
 }
 
