|
|
a59559 |
diff --git a/kdm/backend/dm.c b/kdm/backend/dm.c
|
|
|
a59559 |
index e0f1366..5a5f8a7 100644
|
|
|
a59559 |
--- a/kdm/backend/dm.c
|
|
|
a59559 |
+++ b/kdm/backend/dm.c
|
|
|
a59559 |
@@ -1347,54 +1347,207 @@ getBusyVTs(void)
|
|
|
a59559 |
return activeVTs;
|
|
|
a59559 |
}
|
|
|
a59559 |
|
|
|
a59559 |
+static int
|
|
|
a59559 |
+get_active_vt (void)
|
|
|
a59559 |
+{
|
|
|
a59559 |
+ int console_fd;
|
|
|
a59559 |
+ struct vt_stat console_state = { 0 };
|
|
|
a59559 |
+ console_fd = open ("/dev/tty0", O_RDONLY | O_NOCTTY);
|
|
|
a59559 |
+ if (console_fd < 0) {
|
|
|
a59559 |
+ return 0;
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+ ioctl (console_fd, VT_GETSTATE, &console_state);
|
|
|
a59559 |
+
|
|
|
a59559 |
+ close (console_fd);
|
|
|
a59559 |
+ return console_state.v_active;
|
|
|
a59559 |
+}
|
|
|
a59559 |
+
|
|
|
a59559 |
+static int
|
|
|
a59559 |
+plymouth_is_running (void)
|
|
|
a59559 |
+{
|
|
|
a59559 |
+ static int running = -1;
|
|
|
a59559 |
+ if (running == 0)
|
|
|
a59559 |
+ return 0;
|
|
|
a59559 |
+
|
|
|
a59559 |
+ int status;
|
|
|
a59559 |
+ status = system ("/usr/bin/plymouth --ping");
|
|
|
a59559 |
+
|
|
|
a59559 |
+ running = WIFEXITED (status) && WEXITSTATUS (status) == 0;
|
|
|
a59559 |
+ logWarn ("plymouth is %srunning\n", running?"":"NOT ");
|
|
|
a59559 |
+ return running;
|
|
|
a59559 |
+}
|
|
|
a59559 |
+
|
|
|
a59559 |
+static int
|
|
|
a59559 |
+plymouth_has_active_vt (void)
|
|
|
a59559 |
+{
|
|
|
a59559 |
+ int status;
|
|
|
a59559 |
+ status = system ("/usr/bin/plymouth --has-active-vt");
|
|
|
a59559 |
+
|
|
|
a59559 |
+ return WIFEXITED (status) && WEXITSTATUS (status) == 0;
|
|
|
a59559 |
+}
|
|
|
a59559 |
+
|
|
|
a59559 |
+static int
|
|
|
a59559 |
+plymouth_prepare_for_transition (void)
|
|
|
a59559 |
+{
|
|
|
a59559 |
+ int status;
|
|
|
a59559 |
+ status = system ("/usr/bin/plymouth deactivate");
|
|
|
a59559 |
+
|
|
|
a59559 |
+ return WIFEXITED (status) && WEXITSTATUS (status) == 0;
|
|
|
a59559 |
+}
|
|
|
a59559 |
+
|
|
|
a59559 |
+int
|
|
|
a59559 |
+plymouth_quit_with_transition (void)
|
|
|
a59559 |
+{
|
|
|
a59559 |
+ int status;
|
|
|
a59559 |
+ status = system ("/usr/bin/plymouth --wait quit --retain-splash");
|
|
|
a59559 |
+
|
|
|
a59559 |
+ return WIFEXITED (status) && WEXITSTATUS (status) == 0;
|
|
|
a59559 |
+}
|
|
|
a59559 |
+
|
|
|
a59559 |
+int
|
|
|
a59559 |
+plymouth_quit_without_transition (void)
|
|
|
a59559 |
+{
|
|
|
a59559 |
+ int status;
|
|
|
a59559 |
+ status = system ("/usr/bin/plymouth --wait quit");
|
|
|
a59559 |
+
|
|
|
a59559 |
+ return WIFEXITED (status) && WEXITSTATUS (status) == 0;
|
|
|
a59559 |
+}
|
|
|
a59559 |
+
|
|
|
a59559 |
+static int
|
|
|
a59559 |
+triggered_to_force_display_on_active_vt (void)
|
|
|
a59559 |
+{
|
|
|
a59559 |
+ int should_force_display_on_active_vt;
|
|
|
a59559 |
+ should_force_display_on_active_vt=open("/var/spool/gdm/force-display-on-active-vt", O_RDONLY);
|
|
|
a59559 |
+ if ( should_force_display_on_active_vt >= 0 )
|
|
|
a59559 |
+ close(should_force_display_on_active_vt);
|
|
|
a59559 |
+ unlink("/var/spool/gdm/force-display-on-active-vt");
|
|
|
a59559 |
+ return should_force_display_on_active_vt;
|
|
|
a59559 |
+}
|
|
|
a59559 |
+
|
|
|
a59559 |
static void
|
|
|
a59559 |
allocateVT(struct display *d)
|
|
|
a59559 |
{
|
|
|
a59559 |
struct display *cd;
|
|
|
a59559 |
- int i, tvt, volun;
|
|
|
a59559 |
+ int i, tvt;
|
|
|
a59559 |
|
|
|
a59559 |
if ((d->displayType & d_location) == dLocal &&
|
|
|
a59559 |
d->status == notRunning && !d->serverVT && d->reqSrvVT >= 0)
|
|
|
a59559 |
{
|
|
|
a59559 |
+ /* Try to find the correct VT.
|
|
|
a59559 |
+ * If ServerVT is specified in the config, use it (if the admin used the
|
|
|
a59559 |
+ * same VT for multiple display, it is his/her own fault, no checks done).
|
|
|
a59559 |
+ * Otherwise, walk the list of specified VTs. Positive numbers are used
|
|
|
a59559 |
+ * even if the VT is already in use by a tty. Negative numbers and
|
|
|
a59559 |
+ * unspecified numbers (up to #15) are used if not already in use.
|
|
|
a59559 |
+ * VTs already in use (cd->serverVT) or requested (cd->reqSrvVT)
|
|
|
a59559 |
+ * by any display are skipped.
|
|
|
a59559 |
+ */
|
|
|
a59559 |
+
|
|
|
a59559 |
+ /* some special handling is needed for Plymouth:
|
|
|
a59559 |
+ * if no VT is requested, use the active VT from plymouth for the first
|
|
|
a59559 |
+ * started display.
|
|
|
a59559 |
+ * If the display takes over the VT from plymouth, deactivate plymouth
|
|
|
a59559 |
+ */
|
|
|
a59559 |
+
|
|
|
a59559 |
+ char allowedVTs[16] = { 0 };
|
|
|
a59559 |
if (d->reqSrvVT && d->reqSrvVT < 16) {
|
|
|
a59559 |
- d->serverVT = d->reqSrvVT;
|
|
|
a59559 |
+ allowedVTs[d->reqSrvVT] = 1;
|
|
|
a59559 |
} else {
|
|
|
a59559 |
- for (i = tvt = 0;;) {
|
|
|
a59559 |
- if (serverVTs[i]) {
|
|
|
a59559 |
- tvt = atoi(serverVTs[i++]);
|
|
|
a59559 |
- volun = False;
|
|
|
a59559 |
- if (tvt < 0) {
|
|
|
a59559 |
- tvt = -tvt;
|
|
|
a59559 |
- volun = True;
|
|
|
a59559 |
- }
|
|
|
a59559 |
- if (!tvt || tvt >= 16)
|
|
|
a59559 |
- continue;
|
|
|
a59559 |
- } else {
|
|
|
a59559 |
- if (++tvt >= 16)
|
|
|
a59559 |
- break;
|
|
|
a59559 |
- volun = True;
|
|
|
a59559 |
+ for (i = 0; serverVTs[i]; i++) {
|
|
|
a59559 |
+ tvt = atoi(serverVTs[i]);
|
|
|
a59559 |
+ if ((tvt >= 0) && (tvt < 16)) {
|
|
|
a59559 |
+ allowedVTs[tvt] = 1;
|
|
|
a59559 |
+ } else if (tvt > -16) {
|
|
|
a59559 |
+ allowedVTs[-tvt] = 2;
|
|
|
a59559 |
}
|
|
|
a59559 |
- for (cd = displays; cd; cd = cd->next) {
|
|
|
a59559 |
- if (cd->reqSrvVT == tvt && /* protect from lusers */
|
|
|
a59559 |
- (cd->status != zombie || cd->zstatus != DS_REMOVE))
|
|
|
a59559 |
- goto next;
|
|
|
a59559 |
- if (cd->serverVT == tvt) {
|
|
|
a59559 |
- if (cd->status != zombie || cd->zstatus == DS_REMOTE)
|
|
|
a59559 |
- goto next;
|
|
|
a59559 |
- if (!cd->follower) {
|
|
|
a59559 |
- d->serverVT = -1;
|
|
|
a59559 |
- cd->follower = d;
|
|
|
a59559 |
- return;
|
|
|
a59559 |
- }
|
|
|
a59559 |
- }
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+
|
|
|
a59559 |
+ for (tvt = 15; allowedVTs[tvt] == 0; tvt--) {
|
|
|
a59559 |
+ allowedVTs[tvt] = 2;
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+
|
|
|
a59559 |
+ for (cd = displays; cd; cd = cd->next) {
|
|
|
a59559 |
+ if (cd->status != zombie) {
|
|
|
a59559 |
+ if (cd->reqSrvVT >= 0) allowedVTs[cd->reqSrvVT] = 0;
|
|
|
a59559 |
+ if (cd->serverVT >= 0) allowedVTs[cd->serverVT] = 0;
|
|
|
a59559 |
+ } else if (cd->zstatus == DS_REMOTE) {
|
|
|
a59559 |
+ /* dying, but will spawn new server for remote login */
|
|
|
a59559 |
+ if (cd->serverVT >= 0) allowedVTs[cd->serverVT] = 0;
|
|
|
a59559 |
+ } else if (cd->zstatus != DS_REMOVE) {
|
|
|
a59559 |
+ /* dying, but will be restarted or reserved */
|
|
|
a59559 |
+ if (cd->reqSrvVT >= 0) allowedVTs[cd->reqSrvVT] = 0;
|
|
|
a59559 |
}
|
|
|
a59559 |
- if (!volun || !((1 << tvt) & getBusyVTs())) {
|
|
|
a59559 |
- d->serverVT = tvt;
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+
|
|
|
a59559 |
+ /* check for plymouth using newer methods */
|
|
|
a59559 |
+ d->plymouth_vt = -1;
|
|
|
a59559 |
+ if (plymouth_is_running ()) {
|
|
|
a59559 |
+ if (plymouth_has_active_vt ()) {
|
|
|
a59559 |
+ int vt = get_active_vt ();
|
|
|
a59559 |
+ if (allowedVTs[vt]) {
|
|
|
a59559 |
+ logWarn ("plymouth is active on VT %d, reusing for %s\n", vt, d->name);
|
|
|
a59559 |
+ d->serverVT = vt;
|
|
|
a59559 |
+ d->plymouth_vt = vt;
|
|
|
a59559 |
return;
|
|
|
a59559 |
}
|
|
|
a59559 |
- next: ;
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+ /* fallback to old/deprecated method */
|
|
|
a59559 |
+ } else if ( triggered_to_force_display_on_active_vt() >= 0 ) {
|
|
|
a59559 |
+ int vt = get_active_vt ();
|
|
|
a59559 |
+ if (allowedVTs[vt]) {
|
|
|
a59559 |
+ d->serverVT = vt;
|
|
|
a59559 |
+ return;
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+
|
|
|
a59559 |
+ for (tvt = 0; tvt < 16; tvt++) {
|
|
|
a59559 |
+ if ((allowedVTs[tvt] == 1) ||
|
|
|
a59559 |
+ ((allowedVTs[tvt] == 2) && !((1 << tvt) & getBusyVTs()))) {
|
|
|
a59559 |
+ d->serverVT = tvt;
|
|
|
a59559 |
+ return;
|
|
|
a59559 |
}
|
|
|
a59559 |
}
|
|
|
a59559 |
+
|
|
|
a59559 |
+ for (cd = displays; cd; cd = cd->next) {
|
|
|
a59559 |
+ if ((cd->status == zombie) && (cd->zstatus != DS_REMOTE) &&
|
|
|
a59559 |
+ (cd->follower == 0) && (cd->reqSrvVT != cd->serverVT)) {
|
|
|
a59559 |
+ /* removed; or restarted/reserved on any VT */
|
|
|
a59559 |
+ d->serverVT = -1;
|
|
|
a59559 |
+ cd->follower = d;
|
|
|
a59559 |
+ return;
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+}
|
|
|
a59559 |
+
|
|
|
a59559 |
+static void
|
|
|
a59559 |
+replacePlymouth(void)
|
|
|
a59559 |
+{
|
|
|
a59559 |
+ struct display *cd;
|
|
|
a59559 |
+
|
|
|
a59559 |
+ /* if one display reuses plymouth' VT, plymouth is stopped in the
|
|
|
a59559 |
+ * startServerSuccess/Failed callback (see server.c). In any other
|
|
|
a59559 |
+ * case plymouth is stopped now.
|
|
|
a59559 |
+ */
|
|
|
a59559 |
+ for (cd = displays; cd; cd = cd->next) {
|
|
|
a59559 |
+ if ((cd->serverVT > 0) && (cd->serverVT == cd->plymouth_vt)) {
|
|
|
a59559 |
+ if (cd->status == notRunning) {
|
|
|
a59559 |
+ /* tell plymouth to quit when server has started */
|
|
|
a59559 |
+ logWarn ("plymouth should quit after server startup\n");
|
|
|
a59559 |
+ plymouth_prepare_for_transition ();
|
|
|
a59559 |
+ kickDisplay(cd);
|
|
|
a59559 |
+ return;
|
|
|
a59559 |
+ } else if (cd->status == running) {
|
|
|
a59559 |
+ /* replacing server is starting up, do nothing */
|
|
|
a59559 |
+ return;
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+ }
|
|
|
a59559 |
+
|
|
|
a59559 |
+ if ( plymouth_is_running ()) {
|
|
|
a59559 |
+ plymouth_prepare_for_transition ();
|
|
|
a59559 |
+ plymouth_quit_without_transition ();
|
|
|
a59559 |
}
|
|
|
a59559 |
}
|
|
|
a59559 |
#endif
|
|
|
a59559 |
@@ -1407,6 +1560,7 @@ startDisplays(void)
|
|
|
a59559 |
#ifdef HAVE_VTS
|
|
|
a59559 |
activeVTs = -1;
|
|
|
a59559 |
forEachDisplayRev(allocateVT);
|
|
|
a59559 |
+ replacePlymouth();
|
|
|
a59559 |
#endif
|
|
|
a59559 |
forEachDisplay(kickDisplay);
|
|
|
a59559 |
}
|
|
|
a59559 |
diff --git a/kdm/backend/dm.h b/kdm/backend/dm.h
|
|
|
a59559 |
index 64e106b..930af0e 100644
|
|
|
a59559 |
--- a/kdm/backend/dm.h
|
|
|
a59559 |
+++ b/kdm/backend/dm.h
|
|
|
a59559 |
@@ -304,6 +304,8 @@ struct display {
|
|
|
a59559 |
int authNum; /* number of authorizations */
|
|
|
a59559 |
char *authFile; /* file to store authorization in */
|
|
|
a59559 |
char *greeterAuthFile; /* file to store authorization for greeter in */
|
|
|
a59559 |
+
|
|
|
a59559 |
+ int plymouth_vt; /* Plymouth's VT nr */
|
|
|
a59559 |
};
|
|
|
a59559 |
|
|
|
a59559 |
#define d_location 1
|
|
|
a59559 |
@@ -428,6 +430,9 @@ int anyDisplaysLeft(void);
|
|
|
a59559 |
void forEachDisplay(void (*f)(struct display *));
|
|
|
a59559 |
#ifdef HAVE_VTS
|
|
|
a59559 |
void forEachDisplayRev(void (*f)(struct display *));
|
|
|
a59559 |
+/* function for plymouth */
|
|
|
a59559 |
+int plymouth_quit_with_transition (void);
|
|
|
a59559 |
+int plymouth_quit_without_transition (void);
|
|
|
a59559 |
#endif
|
|
|
a59559 |
void removeDisplay(struct display *old);
|
|
|
a59559 |
struct display
|
|
|
a59559 |
diff --git a/kdm/backend/server.c b/kdm/backend/server.c
|
|
|
a59559 |
index d8dd6f3..8b4708e 100644
|
|
|
a59559 |
--- a/kdm/backend/server.c
|
|
|
a59559 |
+++ b/kdm/backend/server.c
|
|
|
a59559 |
@@ -80,6 +80,7 @@ startServerOnce(void)
|
|
|
a59559 |
char **argv;
|
|
|
a59559 |
|
|
|
a59559 |
debug("startServerOnce for %s, try %d\n", d->name, ++d->startTries);
|
|
|
a59559 |
+
|
|
|
a59559 |
d->serverStatus = starting;
|
|
|
a59559 |
switch (Fork(&d->serverPid)) {
|
|
|
a59559 |
case 0:
|
|
|
a59559 |
@@ -137,6 +138,12 @@ startServerSuccess()
|
|
|
a59559 |
struct display *d = startingServer;
|
|
|
a59559 |
d->serverStatus = ignore;
|
|
|
a59559 |
serverTimeout = TO_INF;
|
|
|
a59559 |
+ if ((d->serverVT > 0) && (d->serverVT == d->plymouth_vt)) {
|
|
|
a59559 |
+ int plymouth_running;
|
|
|
a59559 |
+ logWarn ("Quitting Plymouth with transition\n" );
|
|
|
a59559 |
+ plymouth_running = !plymouth_quit_with_transition ();
|
|
|
a59559 |
+ logWarn ("Is Plymouth still running? %s\n", plymouth_running ? "yes" : "no");
|
|
|
a59559 |
+ }
|
|
|
a59559 |
debug("X server ready, starting session\n");
|
|
|
a59559 |
startDisplayP2(d);
|
|
|
a59559 |
}
|
|
|
a59559 |
@@ -154,6 +161,10 @@ startServerFailed()
|
|
|
a59559 |
startingServer = 0;
|
|
|
a59559 |
logError("X server for display %s cannot be started,"
|
|
|
a59559 |
" session disabled\n", d->name);
|
|
|
a59559 |
+ if ((d->serverVT > 0) && (d->serverVT == d->plymouth_vt)) {
|
|
|
a59559 |
+ logWarn ("Quitting Plymouth without transition\n" );
|
|
|
a59559 |
+ plymouth_quit_without_transition ();
|
|
|
a59559 |
+ }
|
|
|
a59559 |
stopDisplay(d);
|
|
|
a59559 |
}
|
|
|
a59559 |
}
|