#include "strv.h"
#include "unit-name.h"
#include "dbus-service.h"
+#include "special.h"
#define COMMENTS "#;\n"
#define NEWLINES "\n\r"
const RunlevelType type;
} rcnd_table[] = {
/* Standard SysV runlevels */
- { "rc0.d", SPECIAL_RUNLEVEL0_TARGET, RUNLEVEL_DOWN },
- { "rc1.d", SPECIAL_RUNLEVEL1_TARGET, RUNLEVEL_UP },
+ { "rc0.d", SPECIAL_POWEROFF_TARGET, RUNLEVEL_DOWN },
+ { "rc1.d", SPECIAL_RESCUE_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 },
+ { "rc6.d", SPECIAL_REBOOT_TARGET, RUNLEVEL_DOWN },
/* SUSE style boot.d */
{ "boot.d", SPECIAL_SYSINIT_TARGET, RUNLEVEL_SYSINIT },
[SERVICE_STOP_POST] = UNIT_DEACTIVATING,
[SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
[SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SERVICE_MAINTAINANCE] = UNIT_INACTIVE,
+ [SERVICE_MAINTENANCE] = UNIT_INACTIVE,
[SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
};
s->main_pid = 0;
}
+static int service_set_main_pid(Service *s, pid_t pid) {
+ assert(s);
+
+ if (pid <= 1)
+ return -EINVAL;
+
+ if (pid == getpid())
+ return -EINVAL;
+
+ s->main_pid = pid;
+ s->main_pid_known = true;
+
+ return 0;
+}
+
+static int service_set_control_pid(Service *s, pid_t pid) {
+ assert(s);
+
+ if (pid <= 1)
+ return -EINVAL;
+
+ if (pid == getpid())
+ return -EINVAL;
+
+ s->control_pid = pid;
+
+ return 0;
+}
+
static void service_close_socket_fd(Service *s) {
assert(s);
static int service_load_pid_file(Service *s) {
char *k;
- unsigned long p;
int r;
+ pid_t pid;
assert(s);
if ((r = read_one_line_file(s->pid_file, &k)) < 0)
return r;
- if ((r = safe_atolu(k, &p)) < 0) {
- free(k);
- return r;
- }
-
- if ((unsigned long) (pid_t) p != p)
- return -ERANGE;
+ r = parse_pid(k, &pid);
+ free(k);
- if (p <= 1)
- return -ERANGE;
+ if (r < 0)
+ return r;
- if (kill((pid_t) p, 0) < 0 && errno != EPERM) {
- log_warning("PID %llu read from file %s does not exist. Your service or init script might be broken.",
- (unsigned long long) p, s->pid_file);
+ if (kill(pid, 0) < 0 && errno != EPERM) {
+ log_warning("PID %lu read from file %s does not exist. Your service or init script might be broken.",
+ (unsigned long) pid, s->pid_file);
return -ESRCH;
}
- if ((r = unit_watch_pid(UNIT(s), (pid_t) p)) < 0)
- /* FIXME: we need to do something here */
+ if ((r = service_set_main_pid(s, pid)) < 0)
return r;
- s->main_pid = (pid_t) p;
- s->main_pid_known = true;
+ if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
+ /* FIXME: we need to do something here */
+ return r;
return 0;
}
state == SERVICE_STOP_POST ||
state == SERVICE_FINAL_SIGTERM ||
state == SERVICE_FINAL_SIGKILL ||
- state == SERVICE_MAINTAINANCE ||
+ state == SERVICE_MAINTENANCE ||
state == SERVICE_AUTO_RESTART)
service_notify_sockets_dead(s);
service_set_state(s, SERVICE_AUTO_RESTART);
} else
- service_set_state(s, s->failure ? SERVICE_MAINTAINANCE : SERVICE_DEAD);
+ service_set_state(s, s->failure ? SERVICE_MAINTENANCE : SERVICE_DEAD);
return;
static void service_enter_stop(Service *s, bool success) {
int r;
+ pid_t pid;
+
assert(s);
if (!success)
false,
!s->permissions_start_only,
!s->root_directory_start_only,
- &s->control_pid)) < 0)
+ &pid)) < 0)
goto fail;
+ service_set_control_pid(s, pid);
service_set_state(s, SERVICE_STOP);
} else
service_enter_signal(s, SERVICE_STOP_SIGTERM, true);
static void service_enter_start_post(Service *s) {
int r;
+ pid_t pid;
assert(s);
service_unwatch_control_pid(s);
false,
!s->permissions_start_only,
!s->root_directory_start_only,
- &s->control_pid)) < 0)
+ &pid)) < 0)
goto fail;
-
+ service_set_control_pid(s, pid);
service_set_state(s, SERVICE_START_POST);
} else
service_enter_running(s, true);
/* For simple services we immediately start
* the START_POST binaries. */
- s->main_pid = pid;
- s->main_pid_known = true;
-
+ service_set_main_pid(s, pid);
service_enter_start_post(s);
} else if (s->type == SERVICE_FORKING) {
/* For forking services we wait until the start
* process exited. */
- s->control_pid = pid;
-
s->control_command_id = SERVICE_EXEC_START;
s->control_command = s->exec_command[SERVICE_EXEC_START];
+
+ service_set_control_pid(s, pid);
service_set_state(s, SERVICE_START);
} else if (s->type == SERVICE_FINISH ||
* but wait for the bus name to appear on the
* bus. Notify services are similar. */
- s->main_pid = pid;
- s->main_pid_known = true;
-
+ service_set_main_pid(s, pid);
service_set_state(s, SERVICE_START);
} else
assert_not_reached("Unknown service type");
static void service_enter_start_pre(Service *s) {
int r;
+ pid_t pid;
assert(s);
false,
!s->permissions_start_only,
!s->root_directory_start_only,
- &s->control_pid)) < 0)
+ &pid)) < 0)
goto fail;
+ service_set_control_pid(s, pid);
service_set_state(s, SERVICE_START_PRE);
} else
service_enter_start(s);
static void service_enter_reload(Service *s) {
int r;
+ pid_t pid;
assert(s);
false,
!s->permissions_start_only,
!s->root_directory_start_only,
- &s->control_pid)) < 0)
+ &pid)) < 0)
goto fail;
+ service_set_control_pid(s, pid);
service_set_state(s, SERVICE_RELOAD);
} else
service_enter_running(s, true);
static void service_run_next(Service *s, bool success) {
int r;
+ pid_t pid;
assert(s);
assert(s->control_command);
false,
!s->permissions_start_only,
!s->root_directory_start_only,
- &s->control_pid)) < 0)
+ &pid)) < 0)
goto fail;
+ service_set_control_pid(s, pid);
return;
fail:
s->state == SERVICE_START_POST)
return 0;
- assert(s->state == SERVICE_DEAD || s->state == SERVICE_MAINTAINANCE || s->state == SERVICE_AUTO_RESTART);
+ assert(s->state == SERVICE_DEAD || s->state == SERVICE_MAINTENANCE || s->state == SERVICE_AUTO_RESTART);
/* Make sure we don't enter a busy loop of some kind. */
if (!ratelimit_test(&s->ratelimit)) {
unit_serialize_item(u, f, "failure", yes_no(s->failure));
if (s->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", "%u", (unsigned) (s->control_pid));
+ unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
- if (s->main_pid > 0)
- unit_serialize_item_format(u, f, "main-pid", "%u", (unsigned) (s->main_pid));
+ if (s->main_pid_known && s->main_pid > 0)
+ unit_serialize_item_format(u, f, "main-pid", "%lu", (unsigned long) s->main_pid);
unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
else
s->failure = b || s->failure;
} else if (streq(key, "control-pid")) {
- unsigned pid;
+ pid_t pid;
- if ((r = safe_atou(value, &pid)) < 0 || pid <= 0)
+ if ((r = parse_pid(value, &pid)) < 0)
log_debug("Failed to parse control-pid value %s", value);
else
- s->control_pid = (pid_t) pid;
+ service_set_control_pid(s, pid);
} else if (streq(key, "main-pid")) {
- unsigned pid;
+ pid_t pid;
- if ((r = safe_atou(value, &pid)) < 0 || pid <= 0)
+ if ((r = parse_pid(value, &pid)) < 0)
log_debug("Failed to parse main-pid value %s", value);
else
- s->main_pid = (pid_t) pid;
+ service_set_main_pid(s, (pid_t) pid);
} else if (streq(key, "main-pid-known")) {
int b;
break;
case SERVICE_FINAL_SIGKILL:
- log_warning("%s still around after SIGKILL (2). Entering maintainance mode.", u->meta.id);
+ log_warning("%s still around after SIGKILL (2). Entering maintenance mode.", u->meta.id);
service_enter_dead(s, false, true);
break;
s->state == SERVICE_START_POST ||
s->state == SERVICE_RUNNING ||
s->state == SERVICE_RELOAD)) {
- unsigned long pid;
+ pid_t pid;
- if (safe_atolu(e + 8, &pid) < 0 ||
- (unsigned long) (pid_t) pid != pid ||
- pid <= 1)
+ if (parse_pid(e + 8, &pid) < 0)
log_warning("Failed to parse %s", e);
else {
log_debug("%s: got %s", u->meta.id, e);
- s->main_pid = (pid_t) pid;
+ service_set_main_pid(s, pid);
}
}
s->state == SERVICE_START_POST ||
s->state == SERVICE_RUNNING ||
s->state == SERVICE_RELOAD))
- s->main_pid = pid;
+ service_set_main_pid(s, pid);
}
int service_set_socket_fd(Service *s, int fd) {
[SERVICE_STOP_POST] = "stop-post",
[SERVICE_FINAL_SIGTERM] = "final-sigterm",
[SERVICE_FINAL_SIGKILL] = "final-sigkill",
- [SERVICE_MAINTAINANCE] = "maintainance",
+ [SERVICE_MAINTENANCE] = "maintenance",
[SERVICE_AUTO_RESTART] = "auto-restart",
};