chiark / gitweb /
readahead: implement minimal readahead logic based on fanotify(), mincore() and reada...
[elogind.git] / src / service.c
index 1dc3e1ea00d3b38fac9ca7159ce31f3cbb40d342..51a7e6b20f54eed85e0604bb9dee2297cc696f3d 100644 (file)
@@ -231,6 +231,11 @@ static char *sysv_translate_name(const char *name) {
         else if (endswith(name, ".sh"))
                 /* Drop Debian-style .sh suffix */
                 strcpy(stpcpy(r, name) - 3, ".service");
+#ifdef TARGET_ARCH
+       else if (startswith(name, "@"))
+               /* Drop Arch-style background prefix */
+               strcpy(stpcpy(r, name + 1), ".service");
+#endif
         else
                 /* Normal init scripts */
                 strcpy(stpcpy(r, name), ".service");
@@ -260,7 +265,8 @@ static int sysv_translate_facility(const char *name, char **_r) {
 #ifdef TARGET_FEDORA
                 /* Fedora extensions, lacking the $ prefix */
                 "MTA",        SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
-                "smtpdaemon", SPECIAL_MAIL_TRANSFER_AGENT_TARGET
+                "smtpdaemon", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
+                "httpd",      SPECIAL_HTTP_DAEMON_TARGET,
 #endif
         };
 
@@ -276,9 +282,11 @@ static int sysv_translate_facility(const char *name, char **_r) {
                 }
 
         if (*name == '$')
-                return 0;
+                r = unit_name_build(name+1, NULL, ".target");
+        else
+                r = sysv_translate_name(name);
 
-        if (!(r = sysv_translate_name(name)))
+        if (!r)
                 return -ENOMEM;
 
 finish:
@@ -316,8 +324,8 @@ static int sysv_fix_order(Service *s) {
 
                 /* If both units have modern headers we don't care
                  * about the priorities */
-                if ((!s->sysv_path || s->sysv_has_lsb) &&
-                    (!t->sysv_path || t->sysv_has_lsb))
+                if ((s->meta.fragment_path || s->sysv_has_lsb) &&
+                    (t->meta.fragment_path || t->sysv_has_lsb))
                         continue;
 
                 special_s = s->sysv_runlevels && !chars_intersect(RUNLEVELS_UP, s->sysv_runlevels);
@@ -2277,7 +2285,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         assert(s);
         assert(pid >= 0);
 
-        if (s->sysv_path)
+        if (!s->meta.fragment_path)
                 success = is_clean_exit_lsb(code, status);
         else
                 success = is_clean_exit(code, status);
@@ -2655,9 +2663,66 @@ static int service_enumerate(Manager *m) {
         Unit *service;
         Iterator j;
         int r;
+#ifdef TARGET_ARCH
+        Unit *previous = NULL;
+        char *arch_daemons = NULL;
+        char *arch_daemons_stripped = NULL;
+        char **arch_daemons_split = NULL;
+#endif
 
         assert(m);
 
+#ifdef TARGET_ARCH
+        if ((r = parse_env_file("/etc/rc.conf", NEWLINE,
+                                "DAEMONS", &arch_daemons,
+                                NULL)) < 0) {
+
+                if (r != -ENOENT)
+                        log_warning("Failed to read /etc/rc.conf: %s", strerror(-r));
+
+        } else if (arch_daemons) {
+                if (!(arch_daemons_stripped = strchr(arch_daemons, '(')))
+                        arch_daemons_stripped = arch_daemons;
+                else
+                        arch_daemons_stripped++; /* strip start paren */
+
+                arch_daemons_stripped[strcspn(arch_daemons_stripped, ")")] = 0; /* strip end paren */
+
+                if (!(arch_daemons_split = strv_split_quoted(arch_daemons_stripped))) {
+                        r = -ENOMEM;
+                        goto finish;
+                }
+
+                STRV_FOREACH(p, arch_daemons_split) {
+
+                        free(name);
+
+                        if (**p == '!') /* daemons prefixed with ! are disabled, so ignore them */
+                                continue;
+
+                        if (!(name = sysv_translate_name(*p))) {
+                                r = -ENOMEM;
+                                goto finish;
+                        }
+
+                        if ((r = manager_load_unit_prepare(m, name, NULL, NULL, &service)) < 0) {
+                                log_warning("Failed to prepare unit %s: %s", name, strerror(-r));
+                                continue;
+                        }
+
+                        if ((r = unit_add_two_dependencies_by_name_inverse(service, UNIT_AFTER, UNIT_WANTS, "multi-user.target", NULL, true)) < 0)
+                                goto finish;
+
+                        if (previous)
+                                if ((r = unit_add_dependency(service, UNIT_AFTER, previous, true)) < 0)
+                                        goto finish;
+
+                        if (**p != '@') /* daemons prefixed with @ can be started in the background */
+                                previous = service;
+                }
+        }
+#endif
+
         zero(runlevel_services);
 
         STRV_FOREACH(p, m->lookup_paths.sysvrcnd_path)
@@ -2795,6 +2860,10 @@ finish:
         free(path);
         free(fpath);
         free(name);
+#ifdef TARGET_ARCH
+        free(arch_daemons);
+        free(arch_daemons_split);
+#endif
 
         for (i = 0; i < ELEMENTSOF(rcnd_table); i++)
                 set_free(runlevel_services[i]);