chiark / gitweb /
service: optionally, call setsid() on services
[elogind.git] / service.c
index da1c5e78e2a1faa85d429fd6688bf640ea2efebf..8a0034936f57baeadc7eaed8675bcc167a08ff06 100644 (file)
--- a/service.c
+++ b/service.c
@@ -74,6 +74,9 @@ static void service_done(Unit *u) {
         free(s->sysv_path);
         s->sysv_path = NULL;
 
+        free(s->sysv_runlevels);
+        s->sysv_runlevels = NULL;
+
         exec_context_done(&s->exec_context);
         exec_command_free_array(s->exec_command, _SERVICE_EXEC_MAX);
         s->control_command = NULL;
@@ -344,22 +347,38 @@ static int service_load_sysv_path(Service *s, const char *path, UnitLoadState *n
 
                         if (startswith(t, "chkconfig:")) {
                                 int start_priority;
+                                char runlevels[16], *k;
 
                                 state = NORMAL;
 
-                                if (sscanf(t+10, "%*15s %i %*i",
-                                           &start_priority) != 1) {
+                                if (sscanf(t+10, "%15s %i %*i",
+                                           runlevels,
+                                           &start_priority) != 2) {
 
                                         log_warning("[%s:%u] Failed to parse chkconfig line. Ignoring.", path, line);
                                         continue;
                                 }
 
-                                if (start_priority < 0 || start_priority > 99) {
+                                if (start_priority < 0 || start_priority > 99)
                                         log_warning("[%s:%u] Start priority out of range. Ignoring.", path, line);
-                                        continue;
+                                else
+                                        s->sysv_start_priority = start_priority;
+
+                                char_array_0(runlevels);
+                                k = delete_chars(runlevels, WHITESPACE "-");
+
+                                if (k[0]) {
+                                        char *d;
+
+                                        if (!(d = strdup(k))) {
+                                                r = -ENOMEM;
+                                                goto finish;
+                                        }
+
+                                        free(s->sysv_runlevels);
+                                        s->sysv_runlevels = d;
                                 }
 
-                                s->sysv_start_priority = start_priority;
 
                         } else if (startswith(t, "description:")) {
 
@@ -484,20 +503,28 @@ static int service_load_sysv_path(Service *s, const char *path, UnitLoadState *n
                                         if (r == 0)
                                                 continue;
 
-                                        if (!(r = unit_add_dependency_by_name(u, UNIT_AFTER, m)) < 0) {
-                                                free(m);
-                                                goto finish;
-                                        }
-
-                                        r = unit_add_dependency_by_name(
-                                                        u,
-                                                        startswith(t, "Required-Start:") ? UNIT_REQUIRES : UNIT_WANTS,
-                                                        m);
+                                        r = unit_add_dependency_by_name(u, UNIT_AFTER, m);
                                         free(m);
 
                                         if (r < 0)
                                                 goto finish;
                                 }
+                        } else if (startswith(t, "Default-Start:")) {
+                                char *k, *d;
+
+                                state = LSB;
+
+                                k = delete_chars(t+14, WHITESPACE "-");
+
+                                if (k[0] != 0) {
+                                        if (!(d = strdup(k))) {
+                                                r = -ENOMEM;
+                                                goto finish;
+                                        }
+
+                                        free(s->sysv_runlevels);
+                                        s->sysv_runlevels = d;
+                                }
 
                         } else if (startswith(t, "Description:")) {
                                 char *d;
@@ -512,7 +539,8 @@ static int service_load_sysv_path(Service *s, const char *path, UnitLoadState *n
                                 free(u->meta.description);
                                 u->meta.description = d;
 
-                        } else if (startswith(t, "Short-Description:") && !u->meta.description) {
+                        } else if (startswith(t, "Short-Description:") &&
+                                   !u->meta.description) {
                                 char *d;
 
                                 /* We use the short description only
@@ -525,7 +553,6 @@ static int service_load_sysv_path(Service *s, const char *path, UnitLoadState *n
                                         goto finish;
                                 }
 
-                                free(u->meta.description);
                                 u->meta.description = d;
 
                         } else if (state == LSB_DESCRIPTION) {
@@ -565,9 +592,17 @@ static int service_load_sysv_path(Service *s, const char *path, UnitLoadState *n
         if ((r = sysv_exec_commands(s)) < 0)
                 goto finish;
 
-        if ((r = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_BASIC_TARGET)) < 0 ||
-            (r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_BASIC_TARGET)) < 0)
-                goto finish;
+        if (!s->sysv_runlevels || chars_intersect("12345", s->sysv_runlevels)) {
+                /* If there a runlevels configured for this service
+                 * but none of the standard ones, then we assume this
+                 * is some special kind of service (which might be
+                 * needed for early boot) and don't create any links
+                 * to it. */
+
+                if ((r = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_BASIC_TARGET)) < 0 ||
+                    (r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_BASIC_TARGET)) < 0)
+                        goto finish;
+        }
 
         *new_state = UNIT_LOADED;
         r = 0;
@@ -757,6 +792,9 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
                         "%sSysVStartPriority: %i\n",
                         prefix, s->sysv_start_priority);
 
+        if (s->sysv_runlevels)
+                fprintf(f, "%sSysVRunLevels: %s\n",
+                        prefix, s->sysv_runlevels);
 
         free(p2);
 }