]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - src/vt.c
Write utmp records for sessions
[sojka/lightdm.git] / src / vt.c
1 /*
2  * Copyright (C) 2010-2011 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  * 
5  * This program is free software: you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License as published by the Free Software
7  * Foundation, either version 3 of the License, or (at your option) any later
8  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9  * license.
10  */
11
12 #include <string.h>
13 #include <errno.h>
14 #include <unistd.h>
15 #include <glib/gstdio.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <sys/ioctl.h>
19 #ifdef __linux__
20 #include <linux/vt.h>
21 #endif
22
23 #include "vt.h"
24 #include "configuration.h"
25
26 static GList *used_vts = NULL;
27
28 static gint
29 open_console (void)
30 {
31     int fd;
32
33     fd = g_open ("/dev/console", O_RDONLY | O_NOCTTY, 0);
34     if (fd < 0)
35         g_warning ("Error opening /dev/console: %s", strerror (errno));
36     return fd;
37 }
38
39 gint
40 vt_get_active (void)
41 {
42 #ifdef __linux__
43     gint console_fd;
44     gint active = -1;
45
46     /* Pretend always active */
47     if (getuid () != 0)
48         return 1;
49
50     console_fd = open_console ();
51     if (console_fd >= 0)
52     {
53         struct vt_stat console_state = { 0 };
54         if (ioctl (console_fd, VT_GETSTATE, &console_state) < 0)
55             g_warning ("Error using VT_GETSTATE on /dev/console: %s", strerror (errno));
56         else
57             active = console_state.v_active;
58         close (console_fd);
59     }
60
61     return active;
62 #else
63     return -1;
64 #endif
65 }
66
67 void
68 vt_set_active (gint number)
69 {
70 #ifdef __linux__
71     gint console_fd;
72
73     g_debug ("Activating VT %d", number);
74
75     /* Pretend always active */
76     if (getuid () != 0)
77         return;   
78
79     console_fd = open_console ();
80     if (console_fd >= 0)
81     {
82         int n = number;
83
84         if (ioctl (console_fd, VT_ACTIVATE, n) < 0)
85             g_warning ("Error using VT_ACTIVATE %d on /dev/console: %s", n, strerror (errno));
86
87         /* Wait for the VT to become active to avoid a suspected
88          * race condition somewhere between LightDM, X, ConsoleKit and the kernel.
89          * See https://bugs.launchpad.net/bugs/851612 */
90         if (ioctl (console_fd, VT_WAITACTIVE) < 0)
91             g_warning ("Error using VT_WAITACTIVE %d on /dev/console: %s", n, strerror (errno));
92
93         close (console_fd);
94     }
95 #endif
96 }
97
98 static gboolean
99 vt_is_used (gint number)
100 {
101     GList *link;
102
103     for (link = used_vts; link; link = link->next)
104     {
105         int n = GPOINTER_TO_INT (link->data);
106         if (n == number)
107             return TRUE;
108     }
109
110     return FALSE;
111 }
112
113 gint
114 vt_get_min (void)
115 {
116     gint number;
117
118     number = config_get_integer (config_get_instance (), "LightDM", "minimum-vt");
119     if (number < 1)
120         number = 1;
121
122     return number;
123 }
124
125 gint
126 vt_get_unused (void)
127 {
128     gint number;
129
130     if (getuid () != 0)
131         return -1;
132
133     number = vt_get_min ();
134     while (vt_is_used (number))
135         number++;
136  
137     return number;
138 }
139
140 void
141 vt_ref (gint number)
142 {
143     g_debug ("Using VT %d", number);
144     used_vts = g_list_append (used_vts, GINT_TO_POINTER (number)); 
145 }
146
147 void
148 vt_unref (gint number)
149 {
150     g_debug ("Releasing VT %d", number);
151     used_vts = g_list_remove (used_vts, GINT_TO_POINTER (number));
152 }