main.c revision 5022ce717016e7d3e659357812fc04b95bbf17d7
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering This file is part of systemd.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering Copyright 2010 Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering (at your option) any later version.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering systemd is distributed in the hope that it will be useful, but
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering Lesser General Public License for more details.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic bool arg_dump_core = true;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic bool arg_crash_shell = false;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poetteringstatic bool arg_crash_reboot = false;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic bool arg_confirm_spawn = false;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic ShowStatus arg_show_status = _SHOW_STATUS_UNSET;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic bool arg_switched_root = false;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic char ***arg_join_controllers = NULL;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic usec_t arg_default_restart_usec = DEFAULT_RESTART_USEC;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic usec_t arg_default_timeout_start_usec = DEFAULT_TIMEOUT_USEC;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poetteringstatic usec_t arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poetteringstatic usec_t arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poetteringstatic unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poetteringstatic char **arg_default_environment = NULL;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic uint64_t arg_capability_bounding_set_drop = 0;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic nsec_t arg_timer_slack_nsec = NSEC_INFINITY;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic bool arg_default_cpu_accounting = false;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic bool arg_default_blockio_accounting = false;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic bool arg_default_memory_accounting = false;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic bool arg_default_tasks_accounting = false;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic void pager_open_if_enabled(void) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poetteringnoreturn static void freeze_or_reboot(void) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering log_emergency_errno(errno, "Failed to reboot: %m");
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering /* Pass this on immediately, if this is not PID 1 */
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering log_emergency("Caught <%s>, not dumping core.", signal_to_string(sig));
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering /* We want to wait for the core process, hence let's enable SIGCHLD */
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek (void) sigaction(SIGCHLD, &sa, NULL);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering log_emergency_errno(errno, "Caught <%s>, cannot fork for core dump: %m", signal_to_string(sig));
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering else if (pid == 0) {
if (arg_crash_chvt >= 0)
if (arg_crash_shell) {
if (pid < 0)
else if (pid == 0) {
(void) setsid();
(void) make_console_stdio();
static void install_crash_handler(void) {
static int console_setup(void) {
if (tty_fd < 0)
if (!in_initrd())
if (in_initrd())
arg_dump_core = r;
arg_crash_shell = r;
arg_crash_reboot = r;
arg_confirm_spawn = r;
char **env;
if (env)
if (detect_container() > 0)
const char *target;
if (target)
const char *filename, \
unsigned line, \
const char *section, \
unsigned section_line, \
const char *lvalue, \
int ltype, \
const char *rvalue, \
void *data, \
void *userdata) { \
rvalue); \
static int config_parse_cpu_affinity2(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int ncpus;
if (ncpus < 0)
return ncpus;
static int config_parse_show_status(
const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse show status setting, ignoring: %s", rvalue);
static int config_parse_crash_chvt(
const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue);
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
return log_oom();
strv_uniq(l);
strv_free(l);
if (!arg_join_controllers) {
if (!arg_join_controllers) {
strv_free(l);
return log_oom();
arg_join_controllers[0] = l;
strv_free(l);
return log_oom();
for (a = arg_join_controllers; *a; a++) {
if (strv_overlap(*a, l)) {
if (strv_extend_strv(&l, *a, false) < 0) {
strv_free(l);
strv_free_free(t);
return log_oom();
c = strv_copy(*a);
strv_free(l);
strv_free_free(t);
return log_oom();
t[n++] = strv_uniq(l);
arg_join_controllers = t;
static int parse_config_file(void) {
{ "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
#ifdef HAVE_SECCOMP
{ "Manager", "DefaultLimitMEMLOCK", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_MEMLOCK] },
{ "Manager", "DefaultLimitSIGPENDING", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_SIGPENDING] },
{ "Manager", "DefaultLimitMSGQUEUE", config_parse_bytes_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE] },
assert(m);
opterr = 0;
case ARG_LOG_LEVEL:
case ARG_LOG_TARGET:
case ARG_LOG_COLOR:
if (optarg) {
log_show_color(true);
case ARG_LOG_LOCATION:
if (optarg) {
log_show_location(true);
case ARG_DEFAULT_STD_OUTPUT:
case ARG_DEFAULT_STD_ERROR:
case ARG_UNIT:
case ARG_SYSTEM:
case ARG_USER:
case ARG_TEST:
if (arg_no_pager < 0)
arg_no_pager = true;
case ARG_NO_PAGER:
arg_no_pager = true;
case ARG_VERSION:
case ARG_DUMP_CORE:
if (!optarg)
arg_dump_core = true;
arg_dump_core = r;
case ARG_CRASH_CHVT:
case ARG_CRASH_SHELL:
if (!optarg)
arg_crash_shell = true;
arg_crash_shell = r;
case ARG_CRASH_REBOOT:
if (!optarg)
arg_crash_reboot = true;
arg_crash_reboot = r;
case ARG_CONFIRM_SPAWN:
arg_confirm_spawn = r;
case ARG_SHOW_STATUS:
if (optarg) {
case ARG_DESERIALIZE: {
int fd;
FILE *f;
if (r < 0 || fd < 0) {
return -EINVAL;
arg_serialization = f;
case ARG_SWITCHED_ROOT:
arg_switched_root = true;
if (arg_no_pager < 0)
arg_no_pager = true;
return -EINVAL;
return -EINVAL;
static int help(void) {
assert(m);
r = manager_open_serialization(m, &f);
m->n_reloading ++;
bus_manager_send_reloading(m, true);
if (!fds)
return log_oom();
*_f = f;
f = NULL;
if (!rl)
return log_oom();
static void test_usr(void) {
log_warning("/usr appears to be on its own filesystem and is not already mounted. This is not a supported setup. "
"Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information.");
static int initialize_join_controllers(void) {
if (!arg_join_controllers)
return -ENOMEM;
if (!arg_join_controllers[0])
goto oom;
goto oom;
oom:
return -ENOMEM;
#ifdef HAVE_SECCOMP
Iterator i;
void *id;
if (!seccomp)
return log_oom();
if (r == -EEXIST)
goto finish;
goto finish;
static int status_welcome(void) {
NULL);
if (r == -ENOENT)
NULL);
if (r < 0 && r != -ENOENT)
static int write_container_id(void) {
if (isempty(c))
static int bump_unix_max_dgram_qlen(void) {
if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN)
return log_oom();
bool reexecute = false;
bool skip_setup = false;
bool loaded_policy = false;
bool arm_reboot_watchdog = false;
bool queue_default_job = false;
bool empty_etc = false;
#ifdef HAVE_SYSV_COMPAT
skip_setup = true;
skip_setup = false;
umask(0);
log_open();
if (in_initrd())
if (!skip_setup) {
goto finish;
} else if (ima_setup() < 0) {
goto finish;
goto finish;
goto finish;
if (!skip_setup) {
if (clock_is_localtime() > 0) {
int min;
} else if (!in_initrd()) {
log_open();
log_open();
goto finish;
r = initialize_join_controllers();
goto finish;
if (!skip_setup)
kmod_setup();
goto finish;
(void) reset_all_signal_handlers();
if (parse_config_file() < 0) {
goto finish;
goto finish;
geteuid() == 0) {
goto finish;
sd_booted() <= 0) {
goto finish;
running_in_chroot() > 0) {
goto finish;
skip_setup = true;
goto finish;
goto finish;
goto finish;
goto finish;
goto finish;
log_close();
goto finish;
if (arg_serialization)
setsid();
log_open();
goto finish;
v = detect_virtualization();
if (in_initrd())
* /etc/machine-id as flag file. This allows container
if (empty_etc)
_cleanup_free_ char *t;
if (arg_show_status > 0)
test_usr();
goto finish;
goto finish;
if (arg_syscall_archs) {
goto finish;
if (empty_etc) {
r = unit_file_preset_all(UNIT_FILE_SYSTEM, false, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, false, NULL, 0);
goto finish;
if (queue_default_job) {
goto finish;
goto finish;
goto finish;
if (r == -EPERM) {
log_debug("Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
goto finish;
goto finish;
goto finish;
r = manager_loop(m);
goto finish;
switch (m->exit_code) {
case MANAGER_RELOAD:
r = parse_config_file();
r = manager_reload(m);
case MANAGER_REEXECUTE:
goto finish;
reexecute = true;
goto finish;
case MANAGER_SWITCH_ROOT:
if (!switch_root_init)
goto finish;
reexecute = true;
goto finish;
case MANAGER_EXIT:
goto finish;
case MANAGER_REBOOT:
case MANAGER_POWEROFF:
case MANAGER_HALT:
case MANAGER_KEXEC: {
goto finish;
pager_close();
m = manager_free(m);
if (reexecute) {
const char **args;
unsigned i, args_size;
watchdog_close(true);
if (switch_root_dir) {
if (!switch_root_init) {
if (switch_root_dir)
if (switch_root_dir)
(void) clearenv();
(void) make_console_stdio();
(void) reset_all_signal_handlers();
(void) reset_signal_mask();
if (switch_root_init) {
#ifdef HAVE_VALGRIND_VALGRIND_H
if (shutdown_verb) {
switch (log_get_target()) {
case LOG_TARGET_KMSG:
case LOG_TARGET_NULL:
case LOG_TARGET_CONSOLE:
if (log_get_show_color())
if (log_get_show_location())
watchdog_close(r < 0);
watchdog_close(true);
if (detect_container() <= 0)
if (error_message)
return retval;