summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2010-09-18 23:45:00 +0100
committerLennart Poettering <lennart@poettering.net>2010-09-21 01:32:21 +0200
commit980900c1d90b95e594ed0e49dcc11aa59ef14fd2 (patch)
tree809f1e2010bc51505570957befbdd1f14d8f6885
parent5bfcc1c6ef48af20996412dbaac1daa0492a4d41 (diff)
service: start Arch daemons
Arch does not use proper SysV runlevels. Instead /etc/rc.conf contains an array of daemons to load in a multi-user runlevel, and some dependencies between them. This patch enables this behaviour in SystemD (only when compiled with Arch support), which allows SystemD to be a drop in replacement on Arch (modulo some minor bugs). v2: simplified after suggestion from Lennart
-rw-r--r--src/service.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/src/service.c b/src/service.c
index df0d400240..51a7e6b20f 100644
--- a/src/service.c
+++ b/src/service.c
@@ -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");
@@ -2658,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)
@@ -2798,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]);