main.c revision d3b1c5083359faa6cfca81810cf87ef70d0290f6
2818N/A along with systemd; If not, see <http://www.gnu.org/licenses/>.
2899N/A#include "sd-daemon.h"
3817N/A#include "sd-messages.h"
2818N/A#include "load-fragment.h"
2818N/A#include "conf-parser.h"
2818N/A#include "watchdog.h"
2818N/A#include "path-util.h"
2818N/A#include "switch-root.h"
2818N/A#include "capability.h"
2818N/A#include "env-util.h"
6901N/A#include "dbus-manager.h"
6901N/A#include "bus-error.h"
2818N/A#include "bus-util.h"
2818N/A#include "mount-setup.h"
2818N/A#include "loopback-setup.h"
2818N/A#include "hostname-setup.h"
2818N/A#include "machine-id-setup.h"
2818N/A#include "selinux-setup.h"
2818N/A#include "ima-setup.h"
2818N/A#include "smack-setup.h"
2818N/A#include "kmod-setup.h"
4302N/Astatic bool arg_dump_core = true;
3633N/Astatic bool arg_crash_shell = false;
3633N/Astatic bool arg_confirm_spawn = false;
2818N/Astatic bool arg_switched_root = false;
2818N/A else if (!arg_dump_core)
2818N/A if (arg_crash_chvt)
2818N/A if (arg_crash_shell) {
3817N/Astatic void install_crash_handler(void) {
int tty_fd, r;
if (!do_reset)
if (tty_fd < 0) {
return -tty_fd;
static int set_default_unit(const char *u) {
assert(u);
c = strdup(u);
return -ENOMEM;
arg_default_unit = c;
static const char * const rlmap[] = {
if (!in_initrd())
if (in_initrd())
arg_dump_core = r;
arg_crash_shell = r;
arg_confirm_spawn = r;
arg_crash_chvt = k;
if (!cenv)
return -ENOMEM;
char **env;
if (env)
c = word;
"rd.systemd.unit=UNIT Default unit to start when run in initrd\n"
"systemd.crash_shell=0|1 Run shell on crash\n"
"systemd.crash_chvt=N Change to VT #N on crash\n"
"systemd.confirm_spawn=0|1 Confirm every process spawn\n"
"systemd.show_status=0|1|auto Show status updates on the console during bootup\n"
"systemd.default_standard_output=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
"systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
"systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n");
} else if (!in_initrd()) {
const char *filename, \
unsigned line, \
const char *section, \
unsigned section_line, \
const char *lvalue, \
int ltype, \
const char *rvalue, \
void *data, \
void *userdata) { \
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
size_t l;
char *state;
unsigned ncpus = 0;
unsigned cpu;
if (!(t = strndup(w, l)))
return log_oom();
free(t);
return log_oom();
CPU_FREE(c);
return -EBADMSG;
CPU_FREE(c);
static void strv_free_free(char ***l) {
strv_free(*i);
free(l);
static void free_join_controllers(void) {
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char *state, *w;
return log_oom();
free(s);
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) < 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 },
{ "Manager", "DefaultLimitSIGPENDING", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_SIGPENDING] },
const char *fn;
r = config_parse(NULL, fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, false, NULL);
static int parse_proc_cmdline(void) {
char *w, *state;
size_t l;
if (!word)
return log_oom();
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:
case ARG_VERSION:
case ARG_DUMP_CORE:
arg_dump_core = r;
case ARG_CRASH_SHELL:
arg_crash_shell = 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 r < 0 ? r : -EINVAL;
return -errno;
if (arg_serialization)
arg_serialization = f;
case ARG_SWITCHED_ROOT:
arg_switched_root = true;
return -EINVAL;
return -EINVAL;
r = parse_proc_cmdline_word(*a);
static int help(void) {
" --log-target=TARGET Set log target (console, journal, syslog, kmsg, journal-or-kmsg, syslog-or-kmsg, null)\n"
static int version(void) {
assert(m);
r = manager_open_serialization(m, &f);
goto fail;
m->n_reloading ++;
bus_manager_send_reloading(m, true);
if (!fds) {
r = -ENOMEM;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
*_f = f;
fail:
fclose(f);
return -errno;
if (!rl)
return log_oom();
static void test_mtab(void) {
free(p);
"Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
static void test_usr(void) {
log_warning("/usr appears to be on its own filesytem 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 void test_cgroups(void) {
"Consult http://0pointer.de/blog/projects/cgroups-vs-cgroups.html for more information.");
static int initialize_join_controllers(void) {
if (!arg_join_controllers)
return -ENOMEM;
return -ENOMEM;
#ifdef HAVE_SECCOMP
Iterator i;
void *id;
if (!seccomp)
return log_oom();
if (r == -EEXIST)
goto finish;
bool reexecute = false;
bool skip_setup = false;
bool loaded_policy = false;
bool arm_reboot_watchdog = false;
bool queue_default_job = false;
#ifdef HAVE_SYSV_COMPAT
skip_setup = true;
skip_setup = false;
umask(0);
log_open();
if (in_initrd())
if (!skip_setup) {
goto finish;
if (ima_setup() < 0)
goto finish;
if (smack_setup() < 0)
goto finish;
goto finish;
if (!skip_setup) {
if (hwclock_is_localtime() > 0) {
int min;
} else if (!in_initrd()) {
log_open();
log_open();
goto finish;
r = initialize_join_controllers();
goto finish;
goto finish;
if (parse_config_file() < 0)
goto finish;
if (parse_proc_cmdline() < 0)
goto finish;
goto finish;
geteuid() == 0) {
goto finish;
sd_booted() <= 0) {
goto finish;
running_in_chroot() > 0) {
goto finish;
goto finish;
goto finish;
goto finish;
goto finish;
goto finish;
log_close();
goto finish;
if (arg_serialization)
setsid();
log_open();
goto finish;
if (virtualization)
if (in_initrd())
getuid(), t);
#ifdef HAVE_KMOD
kmod_setup();
test_mtab();
test_usr();
test_cgroups();
goto finish;
goto finish;
if (arg_syscall_archs) {
goto finish;
goto finish;
if (arg_serialization) {
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_EXIT:
goto finish;
case MANAGER_RELOAD:
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_REBOOT:
case MANAGER_POWEROFF:
case MANAGER_HALT:
case MANAGER_KEXEC: {
goto finish;
manager_free(m);
m = NULL;
label_finish();
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)
clearenv();
if (arg_serialization) {
if (fds) {
if (switch_root_init) {
if (arg_serialization) {
if (fds) {
#ifdef HAVE_VALGRIND_VALGRIND_H
if (shutdown_verb) {
const char * command_line[] = {
watchdog_close(false);
watchdog_close(true);
freeze();
return retval;