src/seat.c | 7 ++++++- src/session-child.c | 31 +++++++++++++++++++++++++++++++ src/session.c | 25 ++++++++++++++++++++++--- src/session.h | 4 ++-- 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/seat.c b/src/seat.c index 85134180..1707f1e2 100644 --- a/src/seat.c +++ b/src/seat.c @@ -668,7 +668,12 @@ run_session (Seat *seat, Session *session) emit_upstart_signal ("desktop-session-start"); } - session_run (session); + DisplayServer *display_server = session_get_display_server (session); + gint vt_number = display_server_get_vt (display_server); + if (vt_number < 0) + vt_number = 0; + + session_run (session, vt_number); // FIXME: Wait until the session is ready diff --git a/src/session-child.c b/src/session-child.c index eef51e49..e085a32a 100644 --- a/src/session-child.c +++ b/src/session-child.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -483,6 +484,36 @@ session_child_run (int argc, char **argv) command_argv[i] = read_string (); command_argv[i] = NULL; + gint vt_number = 0; + read_data (&vt_number, sizeof (vt_number)); + + // by default, report success if it's not supported or not requested + gint vt_control_result = 1; + +#ifdef __linux__ + if (vt_number > 0) + { + g_autofree gchar *tty_name = g_strdup_printf ("/dev/tty%d", vt_number); + + fd = g_open (tty_name, O_RDONLY | O_NOCTTY, 0); + if (fd >= 0) + { + dup2 (fd, STDIN_FILENO); + close (fd); + + // ioctl TIOCSCTTY could be called here, but it always fails in current conditions + // and it looks like just opening tty is enough to mark it busy + } + else + { + g_warning ("Error opening %s: %s", tty_name, strerror (errno)); + vt_control_result = 0; + } + } +#endif + + write_data (&vt_control_result, sizeof (vt_control_result)); + /* If nothing to run just refresh credentials because we successfully authenticated */ if (command_argc == 0) { diff --git a/src/session.c b/src/session.c index 2ea9352a..889e2863 100644 --- a/src/session.c +++ b/src/session.c @@ -760,12 +760,12 @@ session_get_authentication_result_string (Session *session) } void -session_run (Session *session) +session_run (Session *session, gint vt_number) { SessionPrivate *priv = session_get_instance_private (session); g_return_if_fail (session != NULL); g_return_if_fail (priv->display_server != NULL); - return SESSION_GET_CLASS (session)->run (session); + return SESSION_GET_CLASS (session)->run (session, vt_number); } gboolean @@ -777,15 +777,18 @@ session_get_is_run (Session *session) } static void -session_real_run (Session *session) +session_real_run (Session *session, gint vt_number) { SessionPrivate *priv = session_get_instance_private (session); + const gchar *session_type = session_get_session_type (session); g_return_if_fail (session != NULL); g_return_if_fail (!priv->command_run); g_return_if_fail (session_get_is_authenticated (session)); g_return_if_fail (priv->argv != NULL); g_return_if_fail (priv->pid != 0); + g_return_if_fail (vt_number >= 0); + g_return_if_fail (session_type != NULL); display_server_connect_session (priv->display_server, session); @@ -863,6 +866,20 @@ session_real_run (Session *session) for (gsize i = 0; i < argc; i++) write_string (session, priv->argv[i]); + // only take control of vt for wayland sessions + if (strcmp (session_type, "wayland") != 0) + { + vt_number = 0; + } + + write_data (session, &vt_number, sizeof (vt_number)); + + // wait until child session marks tty busy and reports it + gint vt_control_result = 0; + read_from_child (session, &vt_control_result, sizeof (vt_control_result)); + + l_debug (session, "tty locking result: %d", vt_control_result); + priv->login1_session_id = read_string_from_child (session); priv->console_kit_cookie = read_string_from_child (session); } @@ -945,6 +962,8 @@ session_stop (Session *session) gsize n = 0; write_data (session, &n, sizeof (n)); // environment write_data (session, &n, sizeof (n)); // command + gint vt_number = 0; + write_data (session, &vt_number, sizeof (vt_number)); return; } diff --git a/src/session.h b/src/session.h index 350cf3bb..72d85933 100644 --- a/src/session.h +++ b/src/session.h @@ -54,7 +54,7 @@ typedef struct GObjectClass parent_class; gboolean (*start)(Session *session); - void (*run)(Session *session); + void (*run)(Session *session, gint vt_number); void (*stop)(Session *session); Greeter *(*create_greeter)(Session *session); @@ -136,7 +136,7 @@ int session_get_authentication_result (Session *session); const gchar *session_get_authentication_result_string (Session *session); -void session_run (Session *session); +void session_run (Session *session, gint vt_number); gboolean session_get_is_run (Session *session);