retitle 690892 incomplete support for LSB system facilities
thanks

I've looked into this a bit. The LSB [1] defines the following system
facilities: $local_fs, $network, $named, $portmap, $remote_fs, $syslog,
$time

In addition, in Debian the following system facilities are in use:
$x-display-manager, $mail-transport-agent, $x-font-server

A SysV init script in Debian is not allowed to provide a system
facility. If that is a limitation of insserv or the LSB spec I don't know.
insserv defines the system facilities in /etc/insserv.conf and
/etc/insserv.conf.d/* instead.

systemd maps those system facilities to the following targets/services.
See also man systemd.special:

$local_fs →             local-fs.target
$network →              network.target
$named →                nss-lookup.target
$portmap →              rpcbind.target
$remote_fs →            remote-fs.target
$syslog →               syslog.target
$time →                 time-sync.target
$x-display-manager →    display-manager.service
$mail-transport-agent → mail-transfer-agent.target
$x-font-server →        currently not handled

We can probably ignore the $x-font-server facility as font servers are
pretty much obsolete nowadays.

As for $x-display-manager I'm wondering why this is mapped to a service
instead of a target? In Debian multiple display managers are allowed to
be installed at the same time. So letting one service provide the
display-manager.service symlink/alias won't work afaics.

If a SysV service has a Requires: $system-facility, systemd translates
that into a dependency/ordering (After) on the corresponding target/service.

E.g. the cups LSB header
# Required-Start:    $syslog $remote_fs
# Required-Stop:     $syslog $remote_fs
# Should-Start:      $network avahi
# Should-Stop:       $network

is translated into

After=syslog.target remote-fs.target network.target avahi.service
systemd-journald.socket basic.target


Attached is a fist stab at a patch to read the system facilities defined
by insserv.

After applying this patch and reloading systemd, I e.g. get for
nss-lookup.target:

Requires=dnsmasq.service network.target
Wants=dnsmasq.service lwresd.service bind9.service unbound.service
Conflicts=shutdown.target
Before=mongodb.service exim4.service apache2.service dnsmasq.service
lwresd.service bind9.service unbound.service network.target
After=network.target

An interesting observation here is, that it has both
Requires=dnsmasq.service and Wants=dnsmasq.service

The reason for that is that insserv.conf defines
"$named +named +dnsmasq +lwresd +bind9 +unbound $network"
and the "+" means optional dependency, thus is translated to a Wants.
But after installing dnsmasq, I also have /etc/insserv.conf.d/dnsmasq
containing "$named dnsmasq", i.e. dnsmasq is treated like a required
dependency.
The patch doesn't filter such duplicate entries in the insserv
configuration files.

The patch is based on what's been defined for openSUSE.

Review and comments welcome.

Michael

[1]
http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/facilname.html
-- 
Why is it that all of the instruments seeking intelligent life in the
universe are pointed away from Earth?
diff --git a/src/service.c b/src/service.c
index 808a1b8..9dc721a 100644
--- a/src/service.c
+++ b/src/service.c
@@ -3269,12 +3269,13 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
 
 #ifdef HAVE_SYSV_COMPAT
 
-#ifdef TARGET_SUSE
-static void sysv_facility_in_insserv_conf(Manager *mgr) {
-        FILE *f=NULL;
+#if defined(TARGET_SUSE) || defined(TARGET_DEBIAN)
+static void sysv_parse_insserv_conf(Manager *mgr, const char* filename) {
+        FILE *f = NULL;
         int r;
 
-        if (!(f = fopen("/etc/insserv.conf", "re"))) {
+        if (!(f = fopen(filename, "re"))) {
+                log_error("Failed to open file %s", filename);
                 r = errno == ENOENT ? 0 : -errno;
                 goto finish;
         }
@@ -3288,7 +3289,7 @@ static void sysv_facility_in_insserv_conf(Manager *mgr) {
                                 break;
 
                         r = -errno;
-                        log_error("Failed to read configuration file '/etc/insserv.conf': %s", strerror(-r));
+                        log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
                         goto finish;
                 }
 
@@ -3332,6 +3333,35 @@ finish:
                 fclose(f);
 
 }
+
+static void sysv_facility_in_insserv_conf(Manager *mgr) {
+        DIR *d =NULL;
+        struct dirent *de;
+
+#ifdef TARGET_DEBIAN
+        if (!(d = opendir("/etc/insserv.conf.d/")))
+                if (errno != ENOENT) {
+                       log_warning("opendir() failed on /etc/insserv.conf.d/ %s", strerror(errno));
+                       goto finish;
+                }
+
+        while ((de = readdir(d))) {
+                char *path = NULL;
+                if (ignore_file(de->d_name))
+                        continue;
+
+                path = join("/etc/insserv.conf.d/", de->d_name, NULL);
+                sysv_parse_insserv_conf(mgr, path);
+                free(path);
+        }
+finish:
+        if (d)
+                closedir(d);
+#endif
+
+        sysv_parse_insserv_conf(mgr, "/etc/insserv.conf");
+}
+
 #endif
 
 static int service_enumerate(Manager *m) {
@@ -3482,7 +3512,7 @@ static int service_enumerate(Manager *m) {
 
         r = 0;
 
-#ifdef TARGET_SUSE
+#if defined(TARGET_SUSE) || defined(TARGET_DEBIAN)
         sysv_facility_in_insserv_conf (m);
 #endif
 

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to