chiark / gitweb /
rename basic.la to shared.la and put selinux deps in shared-selinx.la
[elogind.git] / src / login / multi-seat-x.c
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
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
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
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
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"
28 #include "mkdir.h"
29
30 int 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
50         /* If this file is removed, don't forget to remove the code
51          * that invokes this in gdm and other display managers. */
52
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
96                 if (dn) {
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"
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"
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
182 fail:
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 }