1 diff --git a/kdm/backend/dm.c b/kdm/backend/dm.c
2 index e0f1366..5a5f8a7 100644
5 @@ -1347,54 +1347,207 @@ getBusyVTs(void)
13 + struct vt_stat console_state = { 0 };
14 + console_fd = open ("/dev/tty0", O_RDONLY | O_NOCTTY);
15 + if (console_fd < 0) {
18 + ioctl (console_fd, VT_GETSTATE, &console_state);
21 + return console_state.v_active;
25 +plymouth_is_running (void)
27 + static int running = -1;
32 + status = system ("/usr/bin/plymouth --ping");
34 + running = WIFEXITED (status) && WEXITSTATUS (status) == 0;
35 + logWarn ("plymouth is %srunning\n", running?"":"NOT ");
40 +plymouth_has_active_vt (void)
43 + status = system ("/usr/bin/plymouth --has-active-vt");
45 + return WIFEXITED (status) && WEXITSTATUS (status) == 0;
49 +plymouth_prepare_for_transition (void)
52 + status = system ("/usr/bin/plymouth deactivate");
54 + return WIFEXITED (status) && WEXITSTATUS (status) == 0;
58 +plymouth_quit_with_transition (void)
61 + status = system ("/usr/bin/plymouth --wait quit --retain-splash");
63 + return WIFEXITED (status) && WEXITSTATUS (status) == 0;
67 +plymouth_quit_without_transition (void)
70 + status = system ("/usr/bin/plymouth --wait quit");
72 + return WIFEXITED (status) && WEXITSTATUS (status) == 0;
76 +triggered_to_force_display_on_active_vt (void)
78 + int should_force_display_on_active_vt;
79 + should_force_display_on_active_vt=open("/var/spool/gdm/force-display-on-active-vt", O_RDONLY);
80 + if ( should_force_display_on_active_vt >= 0 )
81 + close(should_force_display_on_active_vt);
82 + unlink("/var/spool/gdm/force-display-on-active-vt");
83 + return should_force_display_on_active_vt;
87 allocateVT(struct display *d)
93 if ((d->displayType & d_location) == dLocal &&
94 d->status == notRunning && !d->serverVT && d->reqSrvVT >= 0)
96 + /* Try to find the correct VT.
97 + * If ServerVT is specified in the config, use it (if the admin used the
98 + * same VT for multiple display, it is his/her own fault, no checks done).
99 + * Otherwise, walk the list of specified VTs. Positive numbers are used
100 + * even if the VT is already in use by a tty. Negative numbers and
101 + * unspecified numbers (up to #15) are used if not already in use.
102 + * VTs already in use (cd->serverVT) or requested (cd->reqSrvVT)
103 + * by any display are skipped.
106 + /* some special handling is needed for Plymouth:
107 + * if no VT is requested, use the active VT from plymouth for the first
109 + * If the display takes over the VT from plymouth, deactivate plymouth
112 + char allowedVTs[16] = { 0 };
113 if (d->reqSrvVT && d->reqSrvVT < 16) {
114 - d->serverVT = d->reqSrvVT;
115 + allowedVTs[d->reqSrvVT] = 1;
117 - for (i = tvt = 0;;) {
118 - if (serverVTs[i]) {
119 - tvt = atoi(serverVTs[i++]);
125 - if (!tvt || tvt >= 16)
131 + for (i = 0; serverVTs[i]; i++) {
132 + tvt = atoi(serverVTs[i]);
133 + if ((tvt >= 0) && (tvt < 16)) {
134 + allowedVTs[tvt] = 1;
135 + } else if (tvt > -16) {
136 + allowedVTs[-tvt] = 2;
138 - for (cd = displays; cd; cd = cd->next) {
139 - if (cd->reqSrvVT == tvt && /* protect from lusers */
140 - (cd->status != zombie || cd->zstatus != DS_REMOVE))
142 - if (cd->serverVT == tvt) {
143 - if (cd->status != zombie || cd->zstatus == DS_REMOTE)
145 - if (!cd->follower) {
153 + for (tvt = 15; allowedVTs[tvt] == 0; tvt--) {
154 + allowedVTs[tvt] = 2;
157 + for (cd = displays; cd; cd = cd->next) {
158 + if (cd->status != zombie) {
159 + if (cd->reqSrvVT >= 0) allowedVTs[cd->reqSrvVT] = 0;
160 + if (cd->serverVT >= 0) allowedVTs[cd->serverVT] = 0;
161 + } else if (cd->zstatus == DS_REMOTE) {
162 + /* dying, but will spawn new server for remote login */
163 + if (cd->serverVT >= 0) allowedVTs[cd->serverVT] = 0;
164 + } else if (cd->zstatus != DS_REMOVE) {
165 + /* dying, but will be restarted or reserved */
166 + if (cd->reqSrvVT >= 0) allowedVTs[cd->reqSrvVT] = 0;
168 - if (!volun || !((1 << tvt) & getBusyVTs())) {
173 + /* check for plymouth using newer methods */
174 + d->plymouth_vt = -1;
175 + if (plymouth_is_running ()) {
176 + if (plymouth_has_active_vt ()) {
177 + int vt = get_active_vt ();
178 + if (allowedVTs[vt]) {
179 + logWarn ("plymouth is active on VT %d, reusing for %s\n", vt, d->name);
181 + d->plymouth_vt = vt;
186 + /* fallback to old/deprecated method */
187 + } else if ( triggered_to_force_display_on_active_vt() >= 0 ) {
188 + int vt = get_active_vt ();
189 + if (allowedVTs[vt]) {
195 + for (tvt = 0; tvt < 16; tvt++) {
196 + if ((allowedVTs[tvt] == 1) ||
197 + ((allowedVTs[tvt] == 2) && !((1 << tvt) & getBusyVTs()))) {
203 + for (cd = displays; cd; cd = cd->next) {
204 + if ((cd->status == zombie) && (cd->zstatus != DS_REMOTE) &&
205 + (cd->follower == 0) && (cd->reqSrvVT != cd->serverVT)) {
206 + /* removed; or restarted/reserved on any VT */
216 +replacePlymouth(void)
218 + struct display *cd;
220 + /* if one display reuses plymouth' VT, plymouth is stopped in the
221 + * startServerSuccess/Failed callback (see server.c). In any other
222 + * case plymouth is stopped now.
224 + for (cd = displays; cd; cd = cd->next) {
225 + if ((cd->serverVT > 0) && (cd->serverVT == cd->plymouth_vt)) {
226 + if (cd->status == notRunning) {
227 + /* tell plymouth to quit when server has started */
228 + logWarn ("plymouth should quit after server startup\n");
229 + plymouth_prepare_for_transition ();
232 + } else if (cd->status == running) {
233 + /* replacing server is starting up, do nothing */
239 + if ( plymouth_is_running ()) {
240 + plymouth_prepare_for_transition ();
241 + plymouth_quit_without_transition ();
245 @@ -1407,6 +1560,7 @@ startDisplays(void)
248 forEachDisplayRev(allocateVT);
251 forEachDisplay(kickDisplay);
253 diff --git a/kdm/backend/dm.h b/kdm/backend/dm.h
254 index 64e106b..930af0e 100644
255 --- a/kdm/backend/dm.h
256 +++ b/kdm/backend/dm.h
257 @@ -304,6 +304,8 @@ struct display {
258 int authNum; /* number of authorizations */
259 char *authFile; /* file to store authorization in */
260 char *greeterAuthFile; /* file to store authorization for greeter in */
262 + int plymouth_vt; /* Plymouth's VT nr */
266 @@ -428,6 +430,9 @@ int anyDisplaysLeft(void);
267 void forEachDisplay(void (*f)(struct display *));
269 void forEachDisplayRev(void (*f)(struct display *));
270 +/* function for plymouth */
271 +int plymouth_quit_with_transition (void);
272 +int plymouth_quit_without_transition (void);
274 void removeDisplay(struct display *old);
276 diff --git a/kdm/backend/server.c b/kdm/backend/server.c
277 index d8dd6f3..8b4708e 100644
278 --- a/kdm/backend/server.c
279 +++ b/kdm/backend/server.c
280 @@ -80,6 +80,7 @@ startServerOnce(void)
283 debug("startServerOnce for %s, try %d\n", d->name, ++d->startTries);
285 d->serverStatus = starting;
286 switch (Fork(&d->serverPid)) {
288 @@ -137,6 +138,12 @@ startServerSuccess()
289 struct display *d = startingServer;
290 d->serverStatus = ignore;
291 serverTimeout = TO_INF;
292 + if ((d->serverVT > 0) && (d->serverVT == d->plymouth_vt)) {
293 + int plymouth_running;
294 + logWarn ("Quitting Plymouth with transition\n" );
295 + plymouth_running = !plymouth_quit_with_transition ();
296 + logWarn ("Is Plymouth still running? %s\n", plymouth_running ? "yes" : "no");
298 debug("X server ready, starting session\n");
301 @@ -154,6 +161,10 @@ startServerFailed()
303 logError("X server for display %s cannot be started,"
304 " session disabled\n", d->name);
305 + if ((d->serverVT > 0) && (d->serverVT == d->plymouth_vt)) {
306 + logWarn ("Quitting Plymouth without transition\n" );
307 + plymouth_quit_without_transition ();