From 2d1e0c8938c912f5470e239de7e92ee3617fde81 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 12 Oct 2011 15:50:56 -0400
Subject: [PATCH 1/5] main: fix kernel command line parsing

check_for_consoles has another bug (surprised?) where it would
jump too many characters forward if the command line has
console=tty0 in it, since tty0 is transparently changed to /dev/tty1.
---
 src/main.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/src/main.c b/src/main.c
index 140df67..7e70196 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1827,6 +1827,7 @@ check_for_consoles (state_t    *state,
                                                                  "console=")) != NULL)
     {
       char *end;
+      size_t console_length;
 
       remaining_command_line = console_string;
 
@@ -1839,6 +1840,8 @@ check_for_consoles (state_t    *state,
       if (end != NULL)
         *end = '\0';
 
+      console_length = strlen (console);
+
       if (strcmp (console, "tty0") == 0 || strcmp (console, "/dev/tty0") == 0 ||
           strcmp (console, "tty") == 0 || strcmp (console, "/dev/tty") == 0)
         {
@@ -1849,7 +1852,7 @@ check_for_consoles (state_t    *state,
       ply_trace ("serial console %s found!", console);
       ply_hashtable_insert (consoles, console, NULL);
 
-      remaining_command_line += strlen (console);
+      remaining_command_line += console_length;
     }
 
   free (state->kernel_console_tty);
-- 
1.7.6.2


From 57f6d5d70e82da4483f366ef18345d26f1def794 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 12 Oct 2011 23:32:36 -0400
Subject: [PATCH 2/5] boot-splash: deduce terminal from text display

Right now we pass a terminal to the constructor of the boot splash
object.  This terminal is used for going to KD_TEXT mode when
ctrl-T is tapped or when hiding the splash.

We only need to do this, though, when:

1) we're running on a local vt
2) we're showing graphics

the boot-splash code has all the knowledge it needs to figure these
two things out on its own, and furtermore it already can figure out
which terminal is the relevant one without being told at construct
time.

This commit adds those smarts to the boot splash code.
---
 src/libply-splash-core/ply-boot-splash.c |   63 ++++++++++++++++++++++++-----
 src/libply-splash-core/ply-boot-splash.h |    3 +-
 src/main.c                               |    3 +-
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c
index 173062f..a84910d 100644
--- a/src/libply-splash-core/ply-boot-splash.c
+++ b/src/libply-splash-core/ply-boot-splash.c
@@ -58,7 +58,6 @@ struct _ply_boot_splash
   ply_module_handle_t *module_handle;
   const ply_boot_splash_plugin_interface_t *plugin_interface;
   ply_boot_splash_plugin_t *plugin;
-  ply_terminal_t *terminal;
   ply_keyboard_t *keyboard;
   ply_buffer_t *boot_buffer;
   ply_trigger_t *idle_trigger;
@@ -87,8 +86,7 @@ static void ply_boot_splash_detach_from_event_loop (ply_boot_splash_t *splash);
 ply_boot_splash_t *
 ply_boot_splash_new (const char     *theme_path,
                      const char     *plugin_dir,
-                     ply_buffer_t   *boot_buffer,
-                     ply_terminal_t *terminal)
+                     ply_buffer_t   *boot_buffer)
 {
   ply_boot_splash_t *splash;
 
@@ -102,7 +100,6 @@ ply_boot_splash_new (const char     *theme_path,
   splash->is_shown = false;
 
   splash->boot_buffer = boot_buffer;
-  splash->terminal = terminal;
   splash->pixel_displays = ply_list_new ();
   splash->text_displays = ply_list_new ();
 
@@ -151,6 +148,32 @@ refresh_displays (ply_boot_splash_t *splash)
     }
 }
 
+static ply_terminal_t *
+find_local_console_terminal (ply_boot_splash_t *splash)
+{
+  ply_list_node_t *node;
+  node = ply_list_get_first_node (splash->text_displays);
+
+  while (node != NULL)
+    {
+      ply_text_display_t *display;
+      ply_terminal_t *terminal;
+      ply_list_node_t *next_node;
+
+      display = ply_list_node_get_data (node);
+      next_node = ply_list_get_next_node (splash->text_displays, node);
+
+      terminal = ply_text_display_get_terminal (display);
+
+      if (terminal != NULL && ply_terminal_is_vt (terminal))
+        return terminal;
+
+      node = next_node;
+    }
+
+  return NULL;
+}
+
 static void
 on_keyboard_input (ply_boot_splash_t *splash,
                    const char        *keyboard_input,
@@ -170,13 +193,23 @@ on_keyboard_input (ply_boot_splash_t *splash,
             ply_trace ("toggle text mode!");
             splash->should_force_text_mode = !splash->should_force_text_mode;
 
-            if (splash->should_force_text_mode)
+            if (ply_list_get_length (splash->pixel_displays) >= 1)
               {
-                ply_terminal_set_mode (splash->terminal, PLY_TERMINAL_MODE_TEXT);
-                ply_terminal_ignore_mode_changes (splash->terminal, true);
+                ply_terminal_t *terminal;
+
+                terminal = find_local_console_terminal (splash);
+
+                if (terminal != NULL)
+                  {
+                    if (splash->should_force_text_mode)
+                      {
+                        ply_terminal_set_mode (terminal, PLY_TERMINAL_MODE_TEXT);
+                        ply_terminal_ignore_mode_changes (terminal, true);
+                      }
+                    else
+                      ply_terminal_ignore_mode_changes (terminal, false);
+                  }
               }
-            else
-              ply_terminal_ignore_mode_changes (splash->terminal, false);
             ply_trace ("text mode toggled!");
           return;
 
@@ -616,7 +649,15 @@ ply_boot_splash_hide (ply_boot_splash_t *splash)
   splash->plugin_interface->hide_splash_screen (splash->plugin,
                                                 splash->loop);
 
-  ply_terminal_set_mode (splash->terminal, PLY_TERMINAL_MODE_TEXT);
+  if (ply_list_get_length (splash->pixel_displays) >= 1)
+    {
+      ply_terminal_t *terminal;
+
+      terminal = find_local_console_terminal (splash);
+
+      if (terminal != NULL)
+        ply_terminal_set_mode (terminal, PLY_TERMINAL_MODE_TEXT);
+    }
 
   splash->is_shown = false;
 
@@ -860,7 +901,7 @@ main (int    argc,
                                    (ply_keyboard_escape_handler_t) on_quit, &state);
 
   state.buffer = ply_buffer_new ();
-  state.splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state.buffer, terminal);
+  state.splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state.buffer);
 
   if (!ply_boot_splash_load (state.splash))
     {
diff --git a/src/libply-splash-core/ply-boot-splash.h b/src/libply-splash-core/ply-boot-splash.h
index 1efb8b1..8c66a7f 100644
--- a/src/libply-splash-core/ply-boot-splash.h
+++ b/src/libply-splash-core/ply-boot-splash.h
@@ -43,8 +43,7 @@ typedef void (* ply_boot_splash_on_idle_handler_t) (void *user_data);
 #ifndef PLY_HIDE_FUNCTION_DECLARATIONS
 ply_boot_splash_t *ply_boot_splash_new (const char   *  theme_path,
                                         const char   *  plugin_dir,
-                                        ply_buffer_t *  boot_buffer,
-                                        ply_terminal_t *terminal);
+                                        ply_buffer_t *  boot_buffer);
 
 bool ply_boot_splash_load (ply_boot_splash_t *splash);
 bool ply_boot_splash_load_built_in (ply_boot_splash_t *splash);
diff --git a/src/main.c b/src/main.c
index 7e70196..9f1c6a9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1544,8 +1544,7 @@ start_boot_splash (state_t    *state,
 
   splash = ply_boot_splash_new (theme_path,
                                 PLYMOUTH_PLUGIN_PATH,
-                                state->boot_buffer,
-                                state->terminal);
+                                state->boot_buffer);
 
   is_loaded = ply_boot_splash_load (splash);
   if (!is_loaded && fall_back_if_neccessary)
-- 
1.7.6.2


From 5dbde44f60799c6fdc6d1a86da363d40cd8fe3d5 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 12 Oct 2011 22:38:53 -0400
Subject: [PATCH 3/5] main: don't overwrite state->terminal if there are
 multiple consoles

We call the add_display_and_keyboard_for_terminal function for
every console passed into the kernel command line and once for
/dev/tty1 if no console line is passed in. This function
repeatedly, reinitializes state->terminal with whatever
terminal is passed in each time its called.

This commit changes add_display_and_keyboard_for_terminal to not
touch state->terminal and instead makes the callers do it
(if appropriate)
---
 src/main.c |   56 +++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/src/main.c b/src/main.c
index 9f1c6a9..08b7b7f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -127,8 +127,8 @@ static ply_boot_splash_t *start_boot_splash (state_t    *state,
                                              const char *theme_path,
                                              bool        fall_back_if_neccessary);
 
-static void add_display_and_keyboard_for_terminal (state_t    *state,
-                                                   const char *tty_name);
+static void add_display_and_keyboard_for_terminal (state_t        *state,
+                                                   ply_terminal_t *terminal);
 
 static void add_default_displays_and_keyboard (state_t *state);
 
@@ -1383,18 +1383,14 @@ set_keyboard (state_t        *state,
                                   on_enter, state);
 }
 static void
-add_display_and_keyboard_for_terminal (state_t    *state,
-                                       const char *tty_name)
+add_display_and_keyboard_for_terminal (state_t        *state,
+                                       ply_terminal_t *terminal)
 {
   ply_text_display_t *display;
   ply_keyboard_t *keyboard;
 
-  ply_trace ("adding display and keyboard for %s", tty_name);
-
-  state->terminal = ply_terminal_new (tty_name);
-
-  keyboard = ply_keyboard_new_for_terminal (state->terminal);
-  display = ply_text_display_new (state->terminal);
+  keyboard = ply_keyboard_new_for_terminal (terminal);
+  display = ply_text_display_new (terminal);
 
   ply_list_append_data (state->text_displays, display);
   set_keyboard (state, keyboard);
@@ -1436,31 +1432,28 @@ add_default_displays_and_keyboard (state_t *state)
 {
   ply_renderer_t *renderer;
   ply_keyboard_t *keyboard;
-  ply_terminal_t *terminal;
   ply_text_display_t *text_display;
 
   ply_trace ("adding default displays and keyboard");
 
-  terminal = ply_terminal_new (state->default_tty);
+  state->terminal = ply_terminal_new (state->default_tty);
 
   /* force frame-buffer plugin for shutdown so it sticks around after getting killed */
   if (state->mode == PLY_MODE_SHUTDOWN)
-    renderer = ply_renderer_new (PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", NULL, terminal);
+    renderer = ply_renderer_new (PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", NULL, state->terminal);
   else
-    renderer = ply_renderer_new (NULL, NULL, terminal);
+    renderer = ply_renderer_new (NULL, NULL, state->terminal);
 
   if (!ply_renderer_open (renderer))
     {
       ply_trace ("could not open renderer /dev/fb");
       ply_renderer_free (renderer);
-      ply_terminal_free (terminal);
 
-      add_display_and_keyboard_for_terminal (state, state->default_tty);
+      ply_trace ("adding text display and keyboard for %s", state->default_tty);
+      add_display_and_keyboard_for_terminal (state, state->terminal);
       return;
     }
 
-  state->terminal = terminal;
-
   keyboard = ply_keyboard_new_for_renderer (renderer);
   set_keyboard (state, keyboard);
 
@@ -1801,7 +1794,15 @@ add_display_and_keyboard_for_console (const char *console,
                                       const char *null,
                                       state_t    *state)
 {
-  add_display_and_keyboard_for_terminal (state, console);
+  ply_terminal_t *terminal;
+
+  terminal = ply_terminal_new (console);
+
+  if (strcmp (console, state->default_tty) == 0)
+    state->terminal = terminal;
+
+  ply_trace ("adding display and keyboard for console %s", console);
+  add_display_and_keyboard_for_terminal (state, terminal);
 }
 
 static void
@@ -1827,6 +1828,7 @@ check_for_consoles (state_t    *state,
     {
       char *end;
       size_t console_length;
+      char *console_device;
 
       remaining_command_line = console_string;
 
@@ -1848,8 +1850,20 @@ check_for_consoles (state_t    *state,
           console = strdup (default_tty);
         }
 
-      ply_trace ("serial console %s found!", console);
-      ply_hashtable_insert (consoles, console, NULL);
+      if (strncmp (console, "/dev/", strlen ("/dev/")) == 0)
+        {
+          console_device = console;
+          console = NULL;
+        }
+      else
+        {
+          asprintf (&console_device, "/dev/%s", console);
+          free (console);
+          console = NULL;
+        }
+
+      ply_trace ("serial console %s found!", console_device);
+      ply_hashtable_insert (consoles, console_device, NULL);
 
       remaining_command_line += console_length;
     }
-- 
1.7.6.2


From 8738d99feb0550fc7bd9a203c5af4886b072e3fb Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 13 Oct 2011 00:01:42 -0400
Subject: [PATCH 4/5] main: rename state->terminal to
 state->local_console_terminal

state->terminal is used for VT handling code.  To make it clear
what its role is, rename it to state->local_console_terminal.
---
 src/main.c |   44 ++++++++++++++++++++++----------------------
 1 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/src/main.c b/src/main.c
index 08b7b7f..288e38a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -97,7 +97,7 @@ typedef struct
   ply_command_parser_t *command_parser;
   ply_mode_t mode;
   ply_renderer_t *renderer;
-  ply_terminal_t *terminal;
+  ply_terminal_t *local_console_terminal;
 
   ply_trigger_t *deactivate_trigger;
   ply_trigger_t *quit_trigger;
@@ -871,16 +871,16 @@ quit_splash (state_t *state)
       state->renderer = NULL;
     }
 
-  if (state->terminal != NULL)
+  if (state->local_console_terminal != NULL)
     {
       if (!state->should_retain_splash)
         {
           ply_trace ("Not retaining splash, so deallocating VT");
-          ply_terminal_deactivate_vt (state->terminal);
+          ply_terminal_deactivate_vt (state->local_console_terminal);
         }
-      ply_terminal_close (state->terminal);
-      ply_terminal_free (state->terminal);
-      state->terminal = NULL;
+      ply_terminal_close (state->local_console_terminal);
+      ply_terminal_free (state->local_console_terminal);
+      state->local_console_terminal = NULL;
     }
 
   detach_from_running_session (state);
@@ -970,12 +970,12 @@ deactivate_splash (state_t *state)
 
   detach_from_running_session (state);
 
-  if (state->terminal != NULL)
+  if (state->local_console_terminal != NULL)
     {
       ply_trace ("deactivating terminal");
-      ply_terminal_stop_watching_for_vt_changes (state->terminal);
-      ply_terminal_set_buffered_input (state->terminal);
-      ply_terminal_ignore_mode_changes (state->terminal, true);
+      ply_terminal_stop_watching_for_vt_changes (state->local_console_terminal);
+      ply_terminal_set_buffered_input (state->local_console_terminal);
+      ply_terminal_ignore_mode_changes (state->local_console_terminal, true);
     }
 
   state->is_inactive = true;
@@ -1059,11 +1059,11 @@ on_reactivate (state_t *state)
   if (!state->is_inactive)
     return;
 
-  if (state->terminal != NULL)
+  if (state->local_console_terminal != NULL)
     {
-      ply_terminal_watch_for_vt_changes (state->terminal);
-      ply_terminal_set_unbuffered_input (state->terminal);
-      ply_terminal_ignore_mode_changes (state->terminal, false);
+      ply_terminal_watch_for_vt_changes (state->local_console_terminal);
+      ply_terminal_set_unbuffered_input (state->local_console_terminal);
+      ply_terminal_ignore_mode_changes (state->local_console_terminal, false);
     }
 
   if ((state->session != NULL) && state->should_be_attached)
@@ -1146,8 +1146,8 @@ on_quit (state_t       *state,
 static bool
 on_has_active_vt (state_t *state)
 {
-  if (state->terminal != NULL)
-    return ply_terminal_is_active (state->terminal);
+  if (state->local_console_terminal != NULL)
+    return ply_terminal_is_active (state->local_console_terminal);
   else
     return false;
 }
@@ -1436,13 +1436,13 @@ add_default_displays_and_keyboard (state_t *state)
 
   ply_trace ("adding default displays and keyboard");
 
-  state->terminal = ply_terminal_new (state->default_tty);
+  state->local_console_terminal = ply_terminal_new (state->default_tty);
 
   /* force frame-buffer plugin for shutdown so it sticks around after getting killed */
   if (state->mode == PLY_MODE_SHUTDOWN)
-    renderer = ply_renderer_new (PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", NULL, state->terminal);
+    renderer = ply_renderer_new (PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so", NULL, state->local_console_terminal);
   else
-    renderer = ply_renderer_new (NULL, NULL, state->terminal);
+    renderer = ply_renderer_new (NULL, NULL, state->local_console_terminal);
 
   if (!ply_renderer_open (renderer))
     {
@@ -1450,7 +1450,7 @@ add_default_displays_and_keyboard (state_t *state)
       ply_renderer_free (renderer);
 
       ply_trace ("adding text display and keyboard for %s", state->default_tty);
-      add_display_and_keyboard_for_terminal (state, state->terminal);
+      add_display_and_keyboard_for_terminal (state, state->local_console_terminal);
       return;
     }
 
@@ -1459,7 +1459,7 @@ add_default_displays_and_keyboard (state_t *state)
 
   add_pixel_displays_from_renderer (state, renderer);
 
-  text_display = ply_text_display_new (state->terminal);
+  text_display = ply_text_display_new (state->local_console_terminal);
   ply_list_append_data (state->text_displays, text_display);
 
   state->renderer = renderer;
@@ -1799,7 +1799,7 @@ add_display_and_keyboard_for_console (const char *console,
   terminal = ply_terminal_new (console);
 
   if (strcmp (console, state->default_tty) == 0)
-    state->terminal = terminal;
+    state->local_console_terminal = terminal;
 
   ply_trace ("adding display and keyboard for console %s", console);
   add_display_and_keyboard_for_terminal (state, terminal);
-- 
1.7.6.2


From 3fffc719351b4c38433c7b9850a6cf7da541b453 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 13 Oct 2011 00:26:54 -0400
Subject: [PATCH 5/5] main: close all terminals, not just local console
 terminal

It's important we close all terminals in the shutdown path,
so they all get unlocked and returned to cooked mode.

Previously, we would just close the local console terminal,
which meant other terminals would end up left in a broken state.
---
 src/main.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/src/main.c b/src/main.c
index 288e38a..dfbcc10 100644
--- a/src/main.c
+++ b/src/main.c
@@ -850,9 +850,62 @@ on_show_splash (state_t *state)
   show_messages (state);
 }
 
+static ply_list_t *
+get_tracked_terminals (state_t *state)
+{
+  ply_list_t *terminals;
+  ply_list_node_t *node;
+
+  terminals = ply_list_new ();
+
+  node = ply_list_get_first_node (state->text_displays);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      ply_text_display_t *display;
+      ply_terminal_t *terminal;
+
+      next_node = ply_list_get_next_node (state->text_displays, node);
+      display = ply_list_node_get_data (node);
+      terminal = ply_text_display_get_terminal (display);
+
+      ply_list_append_data (terminals, terminal);
+
+      node = next_node;
+    }
+
+  return terminals;
+}
+
+static void
+free_terminals (state_t    *state,
+                ply_list_t *terminals)
+{
+  ply_list_node_t *node;
+  node = ply_list_get_first_node (terminals);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      ply_terminal_t *terminal;
+
+      next_node = ply_list_get_next_node (state->text_displays, node);
+      terminal = ply_list_node_get_data (node);
+
+      ply_terminal_close (terminal);
+      ply_terminal_free (terminal);
+      ply_list_remove_node (terminals, node);
+
+      node = next_node;
+    }
+
+  ply_list_free (terminals);
+}
+
 static void
 quit_splash (state_t *state)
 {
+  ply_list_t *terminals;
+
   ply_trace ("quiting splash");
   if (state->boot_splash != NULL)
     {
@@ -861,6 +914,8 @@ quit_splash (state_t *state)
       state->boot_splash = NULL;
     }
 
+  terminals = get_tracked_terminals (state);
+
   ply_trace ("removing displays and keyboard");
   remove_displays_and_keyboard (state);
 
@@ -878,11 +933,11 @@ quit_splash (state_t *state)
           ply_trace ("Not retaining splash, so deallocating VT");
           ply_terminal_deactivate_vt (state->local_console_terminal);
         }
-      ply_terminal_close (state->local_console_terminal);
-      ply_terminal_free (state->local_console_terminal);
       state->local_console_terminal = NULL;
     }
 
+  free_terminals (state, terminals);
+
   detach_from_running_session (state);
 }
 
-- 
1.7.6.2

