commit c7791f293660c22fd699020ff1ec1ac83ad94afa
Author: Halton Huo <halton.huo@sun.com>
Date:   Fri Nov 27 21:30:58 2009 +0800

    gdm-08-fbconsole.diff (rework)

diff --git a/acconfig.h b/acconfig.h
index 7a625d2..db32ec0 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -14,6 +14,8 @@
 #undef HAVE_CHPASS
 #undef HAVE_CLEARENV
 #undef HAVE_CRYPT
+#undef FBCONSOLE
+#undef HAVE_FBCONSOLE
 #undef HAVE_GETTEXT
 #undef HAVE_LC_MESSAGES
 #undef HAVE_LIBSM
diff --git a/configure.ac b/configure.ac
index 76b88a0..e6d0e6a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1025,6 +1025,16 @@ fi
 AC_SUBST(XEVIE_OPTION)
 AC_DEFINE_UNQUOTED(XEVIE_OPTION,"$XEVIE_OPTION",[Define xevie option])
 
+# Check for Solaris VT and fbconsole support
+#
+AC_CHECK_HEADERS(sys/vt.h)
+
+AC_PATH_PROG([FBCONSOLE], [fbconsole], no, [$PATH:/usr/X11/bin:/usr/bin])
+if test x$FBCONSOLE != xno ; then
+   AC_DEFINE(HAVE_FBCONSOLE)
+   AC_DEFINE_UNQUOTED([FBCONSOLE], "$FBCONSOLE", [fbconsole program])
+fi
+
 dnl ---------------------------------------------------------------------------
 dnl - Check for audit framework
 dnl ---------------------------------------------------------------------------
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
index 6408d04..c4e3f93 100644
--- a/daemon/gdm-server.c
+++ b/daemon/gdm-server.c
@@ -39,6 +39,12 @@
 #include <glib/gstdio.h>
 #include <glib-object.h>
 
+#ifdef HAVE_FBCONSOLE
+#ifdef HAVE_SYS_VT_H
+#include <sys/vt.h>
+#endif
+#endif
+
 #include <dbus/dbus-glib.h>
 
 #include <X11/Xlib.h> /* for Display */
@@ -69,6 +75,7 @@ struct GdmServerPrivate
 {
         char    *command;
         GPid     pid;
+        GPid     fbconsolepid;
 
         int      priority;
         char    *user_name;
@@ -120,6 +127,128 @@ static void     gdm_server_finalize     (GObject        *object);
 
 G_DEFINE_TYPE (GdmServer, gdm_server, G_TYPE_OBJECT)
 
+#ifdef HAVE_FBCONSOLE
+static void
+gdm_exec_fbconsole (GdmServer *server)
+{
+        gboolean run_fbconsole;
+        char *argv[6];
+
+        run_fbconsole = FALSE;
+
+        if (server->priv->fbconsolepid == 0) {
+
+                g_debug ("Checking if fbconsole should be started");
+
+                if (strcmp (server->priv->display_device, "/dev/console") == 0) {
+                        int fd;
+#ifdef HAVE_SYS_VT_H
+                        int vtstat;
+#endif
+
+                        g_debug ("Running on console");
+
+                        /* If no VT, then run fbconsole */
+                        run_fbconsole = TRUE;
+
+                        /* Set run_fbconsole as TRUE since Xsun
+                           does not support VT at all */
+                        char    *x_server;
+                        char    *out;
+                        char    *command;
+                        char   **arr;
+                        char   **arr1;
+                        int      status;
+                        int      i;
+                        gboolean res;
+                        GError  *error;
+
+                        error = NULL;
+                        out = NULL;
+                        command = g_strdup ("svcprop svc:/application/x11/x11-server");
+
+                        res = g_spawn_command_line_sync (command,
+                                                         &out,
+                                                         NULL,
+                                                         &status,
+                                                         &error);
+                        g_free (command);
+
+                        if (! res) {
+                                g_warning ("Could not get options/server of FMRI x11-server: %s", error->message);
+                                g_error_free (error);
+                                g_free (out);
+                        }
+
+                        x_server = NULL;
+                        arr = g_strsplit (out,"\n", -1);
+                        i = 0;
+                        while (arr [i++] != NULL) {
+                                if (g_str_has_prefix (arr[i], "options/server")) {
+                                        arr1 = g_strsplit (arr[i], " ", -1);
+                                        x_server = g_strdup (arr1[2]);
+                                        g_strfreev (arr1);
+                                        break;
+                                }
+                        }
+                        g_strfreev (arr);
+
+                        if (g_str_has_suffix (x_server, "Xsun")) {
+                                run_fbconsole = TRUE;
+                        } else {
+
+#ifdef HAVE_SYS_VT_H
+                                fd = open ("/dev/vt/0", O_WRONLY);
+                                if (fd > 0) {
+                                        if (ioctl (fd, VT_ENABLED, &vtstat) == 0) {
+                                                if (vtstat == 1) {
+                                                        g_debug ("VT is enabled, so not forking fbconsole");
+                                                        run_fbconsole = FALSE;
+                                                }
+                                        }
+                                }
+
+#endif
+                        }
+
+                        g_free (x_server);
+
+                        if (run_fbconsole == TRUE) {
+                                g_debug ("VT is not enabled, so fork fbconsole");
+                        }
+
+                } else {
+                        g_debug ("Using %s and not on console, so not forking fbconsole",
+                                 server->priv->display_device ? server->priv->display_device : "(null)");
+                }
+        }
+
+        if (run_fbconsole == FALSE) {
+                return;
+        }
+
+        argv[0] = FBCONSOLE;
+        argv[1] = "-n";
+        argv[2] = "-d";
+        argv[3] = server->priv->display_name;
+        argv[4] = NULL;
+
+        g_debug ("Forking fbconsole");
+
+        server->priv->fbconsolepid = fork ();
+        if (server->priv->fbconsolepid == 0) {
+                execv (argv[0], argv);
+
+                g_debug ("Can not start fallback console: %s",
+                         strerror (errno));
+                _exit (0);
+        }
+        if (server->priv->fbconsolepid == -1) {
+                g_debug ("Can not start fallback console");
+        }
+}
+#endif
+
 static char *
 _gdm_server_query_ck_for_display_device (GdmServer *server)
 {
@@ -165,6 +294,10 @@ gdm_server_get_display_device (GdmServer *server)
                 g_object_notify (G_OBJECT (server), "display-device");
         }
 
+#ifdef HAVE_FBCONSOLE
+        gdm_exec_fbconsole (server);
+#endif
+
         return g_strdup (server->priv->display_device);
 }
 
@@ -733,6 +866,15 @@ gdm_server_stop (GdmServer *server)
 {
         int res;
 
+#ifdef HAVE_FBCONSOLE
+        /* Kill fbconsole if it is running */
+        if (server->priv->fbconsolepid > 0) {
+                g_debug ("Killing fbconsole");
+                kill (server->priv->fbconsolepid, SIGTERM);
+        }
+        server->priv->fbconsolepid = 0;
+#endif
+
         if (server->priv->pid <= 1) {
                 return TRUE;
         }
@@ -933,6 +1075,7 @@ gdm_server_init (GdmServer *server)
         server->priv->pid = -1;
         server->priv->command = NULL;
         server->priv->log_dir = g_strdup (LOGDIR);
+        server->priv->fbconsolepid = 0;
 
         add_ready_handler (server);
 }
