chiark / gitweb /
Revert "Implement SocketUser= and SocketGroup= for [Socket]"
[elogind.git] / src / core / service.c
index 8d315c1f7516a3bec166598e318b7ccf8ffef08f..cf084853743550244ae88e711ecf2d35c67bc086 100644 (file)
@@ -390,12 +390,6 @@ static int sysv_translate_facility(const char *name, const char *filename, char
                 "mail-transport-agent", SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
 #endif
 
-#ifdef TARGET_FEDORA
-                "MTA",                  SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
-                "smtpdaemon",           SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
-                "httpd",                SPECIAL_HTTP_DAEMON_TARGET,
-#endif
-
 #ifdef TARGET_SUSE
                 "smtp",                 SPECIAL_MAIL_TRANSFER_AGENT_TARGET,
 #endif
@@ -526,7 +520,7 @@ static ExecCommand *exec_command_new(const char *path, const char *arg1) {
         return c;
 }
 
-static int sysv_exec_commands(Service *s) {
+static int sysv_exec_commands(Service *s, const bool supports_reload) {
         ExecCommand *c;
 
         assert(s);
@@ -543,14 +537,25 @@ static int sysv_exec_commands(Service *s) {
                 return -ENOMEM;
         exec_command_append_list(s->exec_command+SERVICE_EXEC_STOP, c);
 
-        c = exec_command_new(UNIT(s)->source_path, "reload");
-        if (!c)
-                return -ENOMEM;
-        exec_command_append_list(s->exec_command+SERVICE_EXEC_RELOAD, c);
+        if (supports_reload) {
+                c = exec_command_new(UNIT(s)->source_path, "reload");
+                if (!c)
+                        return -ENOMEM;
+                exec_command_append_list(s->exec_command+SERVICE_EXEC_RELOAD, c);
+        }
 
         return 0;
 }
 
+static bool usage_contains_reload(const char *line) {
+        return (strcasestr(line, "{reload|") ||
+                strcasestr(line, "{reload}") ||
+                strcasestr(line, "{reload\"") ||
+                strcasestr(line, "|reload|") ||
+                strcasestr(line, "|reload}") ||
+                strcasestr(line, "|reload\""));
+}
+
 static int service_load_sysv_path(Service *s, const char *path) {
         FILE *f;
         Unit *u;
@@ -560,10 +565,12 @@ static int service_load_sysv_path(Service *s, const char *path) {
                 NORMAL,
                 DESCRIPTION,
                 LSB,
-                LSB_DESCRIPTION
+                LSB_DESCRIPTION,
+                USAGE_CONTINUATION
         } state = NORMAL;
         char *short_description = NULL, *long_description = NULL, *chkconfig_description = NULL, *description;
         struct stat st;
+        bool supports_reload = false;
 
         assert(s);
         assert(path);
@@ -612,8 +619,23 @@ static int service_load_sysv_path(Service *s, const char *path) {
                 line++;
 
                 t = strstrip(l);
-                if (*t != '#')
+                if (*t != '#') {
+                        /* Try to figure out whether this init script supports
+                         * the reload operation. This heuristic looks for
+                         * "Usage" lines which include the reload option. */
+                        if ( state == USAGE_CONTINUATION ||
+                            (state == NORMAL && strcasestr(t, "usage"))) {
+                                if (usage_contains_reload(t)) {
+                                        supports_reload = true;
+                                        state = NORMAL;
+                                } else if (t[strlen(t)-1] == '\\')
+                                        state = USAGE_CONTINUATION;
+                                else
+                                        state = NORMAL;
+                        }
+
                         continue;
+                }
 
                 if (state == NORMAL && streq(t, "### BEGIN INIT INFO")) {
                         state = LSB;
@@ -906,7 +928,7 @@ static int service_load_sysv_path(Service *s, const char *path) {
                 }
         }
 
-        if ((r = sysv_exec_commands(s)) < 0)
+        if ((r = sysv_exec_commands(s, supports_reload)) < 0)
                 goto finish;
         if (s->sysv_runlevels &&
             chars_intersect(RUNLEVELS_BOOT, s->sysv_runlevels) &&
@@ -1161,12 +1183,6 @@ static int service_verify(Service *s) {
                 return -EINVAL;
         }
 
-        if (s->type == SERVICE_ONESHOT &&
-            s->exec_command[SERVICE_EXEC_RELOAD]) {
-                log_error("%s has an ExecReload setting, which is not allowed for Type=oneshot services. Refusing.", UNIT(s)->id);
-                return -EINVAL;
-        }
-
         if (s->type == SERVICE_DBUS && !s->bus_name) {
                 log_error("%s is of type D-Bus but no D-Bus service name has been specified. Refusing.", UNIT(s)->id);
                 return -EINVAL;
@@ -1592,7 +1608,12 @@ static void service_set_state(Service *s, ServiceState state) {
                 cgroup_bonding_trim_list(UNIT(s)->cgroup_bondings, true);
 
         if (old_state != state)
-                log_debug("%s changed %s -> %s", UNIT(s)->id, service_state_to_string(old_state), service_state_to_string(state));
+                log_struct(LOG_DEBUG,
+                           "UNIT=%s", UNIT(s)->id,
+                           "MESSAGE=%s changed %s -> %s", UNIT(s)->id,
+                                   service_state_to_string(old_state),
+                                   service_state_to_string(state),
+                           NULL);
 
         unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
         s->reload_result = SERVICE_SUCCESS;
@@ -1779,7 +1800,8 @@ static int service_spawn(
                 goto fail;
         }
 
-        if (!(our_env = new0(char*, 4))) {
+        our_env = new0(char*, 5);
+        if (!our_env) {
                 r = -ENOMEM;
                 goto fail;
         }
@@ -1802,10 +1824,14 @@ static int service_spawn(
                         goto fail;
                 }
 
-        if (!(final_env = strv_env_merge(2,
-                                         UNIT(s)->manager->environment,
-                                         our_env,
-                                         NULL))) {
+        if (s->meta.manager->running_as != SYSTEMD_SYSTEM)
+                if (asprintf(our_env + n_env++, "MANAGERPID=%lu", (unsigned long) getpid()) < 0) {
+                        r = -ENOMEM;
+                        goto fail;
+                }
+
+        final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL);
+        if (!final_env) {
                 r = -ENOMEM;
                 goto fail;
         }
@@ -2921,8 +2947,16 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                                 f = SERVICE_SUCCESS;
                 }
 
-                log_full(f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
-                         "%s: main process exited, code=%s, status=%i", u->id, sigchld_code_to_string(code), status);
+                log_struct(f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+                           "MESSAGE=%s: main process exited, code=%s, status=%i/%s",
+                                  u->id, sigchld_code_to_string(code), status,
+                                  strna(code == CLD_EXITED
+                                        ? exit_status_to_string(status, EXIT_STATUS_FULL)
+                                        : signal_to_string(status)),
+                           "UNIT=%s", u->id,
+                           "EXIT_CODE=%s", sigchld_code_to_string(code),
+                           "EXIT_STATUS=%i", status,
+                           NULL);
 
                 if (f != SERVICE_SUCCESS)
                         s->result = f;