]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/multi-seat-x.c
relicense to LGPLv2.1 (with exceptions)
[thirdparty/systemd.git] / src / login / multi-seat-x.c
CommitLineData
36db9a8d
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
36db9a8d
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
36db9a8d 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
36db9a8d
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <string.h>
23#include <unistd.h>
24
25#include <libudev.h>
26
27#include "util.h"
49e942b2 28#include "mkdir.h"
36db9a8d
LP
29
30int main(int argc, char *argv[]) {
31
32 struct udev *udev = NULL;
33 struct udev_enumerate *enumerator = NULL;
34 struct udev_list_entry *first, *item;
35 int i;
36 const char *seat = NULL;
37 char **new_argv;
38 char *path = NULL, *device_node = NULL;
39 int r;
40 FILE *f = NULL;
41
42 /* This binary will go away as soon as X natively supports
43 * display enumeration with udev in a way that covers both PCI
44 * and USB. */
45
46 /* This will simply determine the fb device id of the graphics
47 * device assigned to a seat and write a configuration file
48 * from it and then spawn the real X server. */
49
b16f5304
LP
50 /* If this file is removed, don't forget to remove the code
51 * that invokes this in gdm and other display managers. */
52
36db9a8d
LP
53 for (i = 1; i < argc; i++)
54 if (streq(argv[i], "-seat"))
55 seat = argv[i+1];
56
57 if (isempty(seat) || streq(seat, "seat0")) {
58 argv[0] = (char*) X_SERVER;
59 execv(X_SERVER, argv);
60 log_error("Failed to execute real X server: %m");
61 goto fail;
62 }
63
64 udev = udev_new();
65 if (!udev) {
66 log_error("Failed to allocate udev environment.");
67 goto fail;
68 }
69
70 enumerator = udev_enumerate_new(udev);
71 if (!enumerator) {
72 log_error("Failed to allocate udev enumerator.");
73 goto fail;
74 }
75
76 udev_enumerate_add_match_subsystem(enumerator, "graphics");
77 udev_enumerate_add_match_tag(enumerator, seat);
78
79 r = udev_enumerate_scan_devices(enumerator);
80 if (r < 0) {
81 log_error("Failed to enumerate devices.");
82 goto fail;
83 }
84
85 first = udev_enumerate_get_list_entry(enumerator);
86 udev_list_entry_foreach(item, first) {
87 struct udev_device *d;
88 const char *dn;
89
90 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
91 if (!d)
92 continue;
93
94 dn = udev_device_get_devnode(d);
95
be70cdd6 96 if (dn) {
36db9a8d
LP
97 device_node = strdup(dn);
98 if (!device_node) {
99 udev_device_unref(d);
100 log_error("Out of memory.");
101 goto fail;
102 }
103 }
104
105 udev_device_unref(d);
106
107 if (device_node)
108 break;
109 }
110
111 if (!device_node) {
112 log_error("Failed to find device node for seat %s.", seat);
113 goto fail;
114 }
115
116 r = safe_mkdir("/run/systemd/multi-session-x", 0755, 0, 0);
117 if (r < 0) {
118 log_error("Failed to create directory: %s", strerror(-r));
119 goto fail;
120 }
121
122 path = strappend("/run/systemd/multi-session-x/", seat);
123 if (!path) {
124 log_error("Out of memory");
125 goto fail;
126 }
127
128 f = fopen(path, "we");
129 if (!f) {
130 log_error("Failed to write configuration file: %m");
131 goto fail;
132 }
133
134 fprintf(f,
135 "Section \"Device\"\n"
136 " Identifier \"udev\"\n"
137 " Driver \"fbdev\"\n"
138 " Option \"fbdev\" \"%s\"\n"
139 "EndSection\n"
140 "Section \"ServerFlags\"\n"
141 " Option \"AutoAddDevices\" \"True\"\n"
142 " Option \"AllowEmptyInput\" \"True\"\n"
8906b207
RS
143 " Option \"DontVTSwitch\" \"True\"\n"
144 "EndSection\n"
145 "Section \"InputClass\"\n"
146 " Identifier \"Force Input Devices to Seat\"\n"
147 " Option \"GrabDevice\" \"True\"\n"
36db9a8d
LP
148 "EndSection\n",
149 device_node);
150
151 fflush(f);
152
153 if (ferror(f)) {
154 log_error("Failed to write configuration file: %m");
155 goto fail;
156 }
157
158 fclose(f);
159 f = NULL;
160
161 new_argv = alloca(sizeof(char*) * (argc + 3 + 1));
162 memcpy(new_argv, argv, sizeof(char*) * (argc + 2 + 1));
163
164 new_argv[0] = (char*) X_SERVER;
165 new_argv[argc+0] = (char*) "-config";
166 new_argv[argc+1] = path;
167 new_argv[argc+2] = (char*) "-sharevts";
168 new_argv[argc+3] = NULL;
169
170 udev_enumerate_unref(enumerator);
171 enumerator = NULL;
172
173 udev_unref(udev);
174 udev = NULL;
175
176 free(device_node);
177 device_node = NULL;
178
179 execv(X_SERVER, new_argv);
180 log_error("Failed to execute real X server: %m");
181
182fail:
183 if (enumerator)
184 udev_enumerate_unref(enumerator);
185
186 if (udev)
187 udev_unref(udev);
188
189 free(path);
190 free(device_node);
191
192 if (f)
193 fclose(f);
194
195 return EXIT_FAILURE;
196}