Back to index

lightdm  1.3.2
vt.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010-2011 Robert Ancell.
00003  * Author: Robert Ancell <robert.ancell@canonical.com>
00004  * 
00005  * This program is free software: you can redistribute it and/or modify it under
00006  * the terms of the GNU General Public License as published by the Free Software
00007  * Foundation, either version 3 of the License, or (at your option) any later
00008  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
00009  * license.
00010  */
00011 
00012 #include <string.h>
00013 #include <errno.h>
00014 #include <unistd.h>
00015 #include <glib/gstdio.h>
00016 #include <sys/stat.h>
00017 #include <fcntl.h>
00018 #include <sys/ioctl.h>
00019 #ifdef __linux__
00020 #include <linux/vt.h>
00021 #endif
00022 
00023 #include "vt.h"
00024 #include "configuration.h"
00025 
00026 static GList *used_vts = NULL;
00027 
00028 static gint
00029 open_console (void)
00030 {
00031     int fd;
00032 
00033     fd = g_open ("/dev/console", O_RDONLY | O_NOCTTY, 0);
00034     if (fd < 0)
00035         g_warning ("Error opening /dev/console: %s", strerror (errno));
00036     return fd;
00037 }
00038 
00039 gint
00040 vt_get_active (void)
00041 {
00042 #ifdef __linux__
00043     gint console_fd;
00044     gint active = -1;
00045 
00046     /* Pretend always active */
00047     if (getuid () != 0)
00048         return 1;
00049 
00050     console_fd = open_console ();
00051     if (console_fd >= 0)
00052     {
00053         struct vt_stat console_state = { 0 };
00054         if (ioctl (console_fd, VT_GETSTATE, &console_state) < 0)
00055             g_warning ("Error using VT_GETSTATE on /dev/console: %s", strerror (errno));
00056         else
00057             active = console_state.v_active;
00058         close (console_fd);
00059     }
00060 
00061     return active;
00062 #else
00063     return -1;
00064 #endif
00065 }
00066 
00067 void
00068 vt_set_active (gint number)
00069 {
00070 #ifdef __linux__
00071     gint console_fd;
00072 
00073     g_debug ("Activating VT %d", number);
00074 
00075     /* Pretend always active */
00076     if (getuid () != 0)
00077         return;   
00078 
00079     console_fd = open_console ();
00080     if (console_fd >= 0)
00081     {
00082         int n = number;
00083 
00084         if (ioctl (console_fd, VT_ACTIVATE, n) < 0)
00085             g_warning ("Error using VT_ACTIVATE %d on /dev/console: %s", n, strerror (errno));
00086 
00087         /* Wait for the VT to become active to avoid a suspected
00088          * race condition somewhere between LightDM, X, ConsoleKit and the kernel.
00089          * See https://bugs.launchpad.net/bugs/851612 */
00090         if (ioctl (console_fd, VT_WAITACTIVE) < 0)
00091             g_warning ("Error using VT_WAITACTIVE %d on /dev/console: %s", n, strerror (errno));
00092 
00093         close (console_fd);
00094     }
00095 #endif
00096 }
00097 
00098 static gboolean
00099 vt_is_used (gint number)
00100 {
00101     GList *link;
00102 
00103     for (link = used_vts; link; link = link->next)
00104     {
00105         int n = GPOINTER_TO_INT (link->data);
00106         if (n == number)
00107             return TRUE;
00108     }
00109 
00110     return FALSE;
00111 }
00112 
00113 gint
00114 vt_get_min (void)
00115 {
00116     gint number;
00117 
00118     number = config_get_integer (config_get_instance (), "LightDM", "minimum-vt");
00119     if (number < 1)
00120         number = 1;
00121 
00122     return number;
00123 }
00124 
00125 gint
00126 vt_get_unused (void)
00127 {
00128     gint number;
00129 
00130     if (getuid () != 0)
00131         return -1;
00132 
00133     number = vt_get_min ();
00134     while (vt_is_used (number))
00135         number++;
00136  
00137     return number;
00138 }
00139 
00140 void
00141 vt_ref (gint number)
00142 {
00143     g_debug ("Using VT %d", number);
00144     used_vts = g_list_append (used_vts, GINT_TO_POINTER (number)); 
00145 }
00146 
00147 void
00148 vt_unref (gint number)
00149 {
00150     g_debug ("Releasing VT %d", number);
00151     used_vts = g_list_remove (used_vts, GINT_TO_POINTER (number));
00152 }