From: Tom Gundersen Date: Sat, 18 Sep 2010 22:45:00 +0000 (+0100) Subject: service: start Arch daemons X-Git-Tag: v11~118 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=980900c1d90b95e594ed0e49dcc11aa59ef14fd2 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 --- diff --git a/src/service.c b/src/service.c index df0d40024..51a7e6b20 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]);