From 3cd56ae5c539508182e7ee482f6ca4a3ad3d1eaf Mon Sep 17 00:00:00 2001
From: Didier Roche <didrocks@ubuntu.com>
Date: Thu, 27 Nov 2014 12:49:15 +0100
Subject: [PATCH 2/3] Mask sysvinit-only dms if not default.

Modify insserv generator to mask of sysvinit-only dms with insserv
$x-display-manager tag if they don't match /etc/X11/default-display-manager.
This avoids starting multiple dms at boot.
---
 debian/changelog                                   |  6 ++-
 ...r-rcS.d-services-after-local-fs.target-if.patch |  4 +-
 debian/patches/insserv.conf-generator.patch        | 62 ++++++++++++++++++++--
 3 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 758bfdf..f1aa3ef 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -14,9 +14,13 @@ systemd (217-1) UNRELEASED; urgency=medium
     changed/missing symbols during build.
 
   [ Didier Roche ]
-  * Handle display-manager transitions:
+  * Handle display-manager transitions: (Closes: #748668)
     - Add a generator to ensure /etc/X11/default-display-manager is controlling
       which display-manager is started.
+    - Modify insserv generator to mask of sysvinit-only dms with insserv
+      $x-display-manager tag if they don't match
+      /etc/X11/default-display-manager. This avoids starting multiple dms at
+      boot.
 
  -- Martin Pitt <mpitt@debian.org>  Wed, 19 Nov 2014 08:06:34 +0100
 
diff --git a/debian/patches/Do-not-order-rcS.d-services-after-local-fs.target-if.patch b/debian/patches/Do-not-order-rcS.d-services-after-local-fs.target-if.patch
index e9f217f..0964757 100644
--- a/debian/patches/Do-not-order-rcS.d-services-after-local-fs.target-if.patch
+++ b/debian/patches/Do-not-order-rcS.d-services-after-local-fs.target-if.patch
@@ -31,10 +31,10 @@ index 863d7f3..ec63e74 100644
                          </varlistentry>
                          <varlistentry>
 diff --git a/src/insserv-generator/insserv-generator.c b/src/insserv-generator/insserv-generator.c
-index d86ee29..6c10735 100644
+index 0419dc7..9b04d7e 100644
 --- a/src/insserv-generator/insserv-generator.c
 +++ b/src/insserv-generator/insserv-generator.c
-@@ -62,7 +62,7 @@ static int sysv_translate_facility(const char *name, const char *filename, char
+@@ -64,7 +64,7 @@ static int sysv_translate_facility(const char *name, const char *filename, char
  
          static const char * const table[] = {
                  /* LSB defined facilities */
diff --git a/debian/patches/insserv.conf-generator.patch b/debian/patches/insserv.conf-generator.patch
index 8395498..cd0bef8 100644
--- a/debian/patches/insserv.conf-generator.patch
+++ b/debian/patches/insserv.conf-generator.patch
@@ -12,13 +12,16 @@ It has the following modifications:
 - it removes support for boot. and bool.localfs which is a SuSE specific
   extension
 - it ensures that targets do not start other targets or services
+- it masks all sysvinit display managers (tagged with an insserv
+  $x-display-manager) not matching /etc/X11/default-display-manager, and
+  doesn't generate units having systemd system units already.
 
 [0] https://build.opensuse.org/package/view_file/openSUSE:Factory/systemd/insserv-generator.patch
 ---
  Makefile.am                               |   9 +
  src/insserv-generator/Makefile            |  28 +++
- src/insserv-generator/insserv-generator.c | 324 ++++++++++++++++++++++++++++++
- 3 files changed, 361 insertions(+)
+ src/insserv-generator/insserv-generator.c | 377 ++++++++++++++++++++++++++++++
+ 3 files changed, 414 insertions(+)
  create mode 100644 src/insserv-generator/Makefile
  create mode 100644 src/insserv-generator/insserv-generator.c
 
@@ -85,10 +88,10 @@ index 0000000..9d07505
 +.PHONY: all clean
 diff --git a/src/insserv-generator/insserv-generator.c b/src/insserv-generator/insserv-generator.c
 new file mode 100644
-index 0000000..d86ee29
+index 0000000..0419dc7
 --- /dev/null
 +++ b/src/insserv-generator/insserv-generator.c
-@@ -0,0 +1,324 @@
+@@ -0,0 +1,373 @@
 +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 +
 +/***
@@ -125,6 +128,8 @@ index 0000000..d86ee29
 +#include "strv.h"
 +
 +static const char *arg_dest = "/tmp";
++static const char *arg_override = "/tmp";
++static const char *default_dm = NULL;
 +
 +static char *sysv_translate_name(const char *name) {
 +        char *r;
@@ -212,10 +217,47 @@ index 0000000..d86ee29
 +}
 +
 +
++/* if we have a display-manager which doesn't match /etc/X11/default-display-manager, and don't have
++   an unit file, we mask it to simulate the init script behavior */
++static int mask_display_manager_init(const char *name) {
++        static const char *default_dm_file = "/etc/X11/default-display-manager";
++        _cleanup_free_ char *default_dm_path = NULL;
++        const char *in_mem_symlink = NULL;
++        int r;
++
++        if (!default_dm) {
++                r = read_full_file(default_dm_file, &default_dm_path, NULL);
++                if (r >= 0)
++                        default_dm = strstrip(basename((char *)default_dm_path));
++                else
++                       /* ensure we won't match any non systemd init. The old init script won't have started anyway */
++                       default_dm = "";
++        }
++
++        /* init script is default dm, nothing to do */
++        if (streq(default_dm, name))
++                return 0;
++
++        in_mem_symlink = strappenda(arg_override, "/", name, ".service");
++        mkdir_parents_label(in_mem_symlink, 0755);
++        if (symlink("/dev/null", in_mem_symlink) < 0) {
++                log_error("Failed to create symlink %s: %m", in_mem_symlink);
++                return -errno;
++        }
++
++        return 0;
++}
++
 +
 +static int parse_insserv_conf(const char* filename) {
 +        _cleanup_fclose_ FILE *f = NULL;
 +        int r;
++        const char *target_unit_path = NULL;
++
++        /* skip if we have a system a corresponding unit file */
++        target_unit_path = strappenda(SYSTEM_DATA_UNIT_PATH, "/", basename(filename), ".service");
++        if (access(target_unit_path, F_OK) >= 0)
++                return 0;
 +
 +        if (!(f = fopen(filename, "re"))) {
 +                log_debug("Failed to open file %s", filename);
@@ -297,6 +339,14 @@ index 0000000..d86ee29
 +                                                }
 +                                        }
 +
++                                        if (streq(parsed[0], "$x-display-manager")) {
++                                                r = mask_display_manager_init(name);
++                                                /* we couldn't create the override symlink, with some luck, nothing else than x-display-manager
++                                                   will pull it in the dep chain */
++                                                if (r < 0)
++                                                        continue;
++                                        }
++
 +                                        unit = strjoin(arg_dest, "/", dep, ".d/50-",basename(filename),"-",parsed[0],".conf", NULL);
 +                                        if (!unit)
 +                                                return log_oom();
@@ -400,8 +450,10 @@ index 0000000..d86ee29
 +                return EXIT_FAILURE;
 +        }
 +
-+        if (argc > 1)
++        if (argc > 1) {
 +                arg_dest = argv[1];
++                arg_override = argv[2];
++        }
 +
 +        log_set_target(LOG_TARGET_SAFE);
 +        log_parse_environment();
-- 
2.1.3

