summaryrefslogtreecommitdiff
path: root/service.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-05-13 22:24:22 +0200
committerLennart Poettering <lennart@poettering.net>2010-05-13 22:24:22 +0200
commitfbe9f3a92dcb585c14faf06ef9017f552e405222 (patch)
tree6fbfdde63d4ba9aa5beb1d5c49d83785ce6001aa /service.c
parent31cee6f634ce07aa2c3514a506f93830f91f14a5 (diff)
sysv: rework suse/debian special bootup runlevel handling
Diffstat (limited to 'service.c')
-rw-r--r--service.c73
1 files changed, 57 insertions, 16 deletions
diff --git a/service.c b/service.c
index b208e9e0bc..c13cf2f5e1 100644
--- a/service.c
+++ b/service.c
@@ -37,7 +37,6 @@
#define NEWLINES "\n\r"
#define LINE_MAX 4096
-
typedef enum RunlevelType {
RUNLEVEL_UP,
RUNLEVEL_DOWN,
@@ -49,18 +48,25 @@ static const struct {
const char *target;
const RunlevelType type;
} rcnd_table[] = {
- { "/rc0.d", SPECIAL_RUNLEVEL0_TARGET, RUNLEVEL_DOWN },
- { "/rc1.d", SPECIAL_RUNLEVEL1_TARGET, RUNLEVEL_UP },
- { "/rc2.d", SPECIAL_RUNLEVEL2_TARGET, RUNLEVEL_UP },
- { "/rc3.d", SPECIAL_RUNLEVEL3_TARGET, RUNLEVEL_UP },
- { "/rc4.d", SPECIAL_RUNLEVEL4_TARGET, RUNLEVEL_UP },
- { "/rc5.d", SPECIAL_RUNLEVEL5_TARGET, RUNLEVEL_UP },
- { "/rc6.d", SPECIAL_RUNLEVEL6_TARGET, RUNLEVEL_DOWN },
- { "/boot.d", SPECIAL_BASIC_TARGET, RUNLEVEL_BASIC },
+ /* Standard SysV runlevels */
+ { "rc0.d", SPECIAL_RUNLEVEL0_TARGET, RUNLEVEL_DOWN },
+ { "rc1.d", SPECIAL_RUNLEVEL1_TARGET, RUNLEVEL_UP },
+ { "rc2.d", SPECIAL_RUNLEVEL2_TARGET, RUNLEVEL_UP },
+ { "rc3.d", SPECIAL_RUNLEVEL3_TARGET, RUNLEVEL_UP },
+ { "rc4.d", SPECIAL_RUNLEVEL4_TARGET, RUNLEVEL_UP },
+ { "rc5.d", SPECIAL_RUNLEVEL5_TARGET, RUNLEVEL_UP },
+ { "rc6.d", SPECIAL_RUNLEVEL6_TARGET, RUNLEVEL_DOWN },
+
+ /* SuSE style boot.d */
+ { "boot.d", SPECIAL_BASIC_TARGET, RUNLEVEL_BASIC },
+
+ /* Debian style rcS.d */
+ { "rcS.d", SPECIAL_BASIC_TARGET, RUNLEVEL_BASIC },
};
#define RUNLEVELS_UP "12345"
-#define RUNLEVELS_DOWN "06"
+/* #define RUNLEVELS_DOWN "06" */
+/* #define RUNLEVELS_BOOT "bBsS" */
static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
[SERVICE_DEAD] = UNIT_INACTIVE,
@@ -368,6 +374,9 @@ static int service_load_sysv_path(Service *s, const char *path) {
continue;
}
+ /* A start priority gathered from the
+ * symlink farms is preferred over the
+ * data from the LSB header. */
if (start_priority < 0 || start_priority > 99)
log_warning("[%s:%u] Start priority out of range. Ignoring.", path, line);
else if (s->sysv_start_priority < 0)
@@ -640,8 +649,26 @@ static int service_load_sysv_name(Service *s, const char *name) {
path[strlen(path)-8] = 0;
r = service_load_sysv_path(s, path);
+
+ if (r >= 0 && UNIT(s)->meta.load_state == UNIT_STUB) {
+ /* Try Debian style .sh source'able init scripts */
+ strcat(path, ".sh");
+ r = service_load_sysv_path(s, path);
+ }
+
free(path);
+ if (r >= 0 && UNIT(s)->meta.load_state == UNIT_STUB) {
+ /* Try Suse style boot.xxxx init scripts */
+
+ if (asprintf(&path, "%s/boot.%s", *p, name) < 0)
+ return -ENOMEM;
+
+ path[strlen(path)-8] = 0;
+ r = service_load_sysv_path(s, path);
+ free(path);
+ }
+
if (r < 0)
return r;
@@ -2189,18 +2216,30 @@ static int service_enumerate(Manager *m) {
}
free(name);
- name = NULL;
- if (asprintf(&name, "%s.service", de->d_name+3) < 0) {
+ if (!(name = new(char, strlen(de->d_name) - 3 + 8 + 1))) {
r = -ENOMEM;
goto finish;
}
- if ((r = manager_load_unit_prepare(m, name, NULL, &service)) < 0)
- goto finish;
+ if (startswith(de->d_name+3, "boot."))
+ /* Drop SuSE-style boot. prefix */
+ strcpy(stpcpy(name, de->d_name + 3 + 5), ".service");
+ else if (endswith(de->d_name+3, ".sh"))
+ /* Drop Debian-style .sh suffix */
+ strcpy(stpcpy(name, de->d_name + 3) - 3, ".service");
+ else
+ /* Normal init scripts */
+ strcpy(stpcpy(name, de->d_name + 3), ".service");
+
+ if ((r = manager_load_unit_prepare(m, name, NULL, &service)) < 0) {
+ log_warning("Failed to prepare unit %s: %s", name, strerror(-r));
+ continue;
+ }
if (de->d_name[0] == 'S' &&
(rcnd_table[i].type == RUNLEVEL_UP || rcnd_table[i].type == RUNLEVEL_BASIC))
- SERVICE(service)->sysv_start_priority = a*10 + b;
+ SERVICE(service)->sysv_start_priority =
+ MAX(a*10 + b, SERVICE(service)->sysv_start_priority);
manager_dispatch_load_queue(m);
service = unit_follow_merge(service);
@@ -2249,7 +2288,9 @@ finish:
free(path);
free(fpath);
free(name);
- closedir(d);
+
+ if (d)
+ closedir(d);
return r;
}