diff options
author | Tom Gundersen <teg@jklm.no> | 2010-09-18 23:45:00 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2010-09-21 01:32:21 +0200 |
commit | 980900c1d90b95e594ed0e49dcc11aa59ef14fd2 (patch) | |
tree | 809f1e2010bc51505570957befbdd1f14d8f6885 /src/service.c | |
parent | 5bfcc1c6ef48af20996412dbaac1daa0492a4d41 (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
Diffstat (limited to 'src/service.c')
-rw-r--r-- | src/service.c | 66 |
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]); |