X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsystemctl.c;h=eacc63e94dd2c45c98f2e96b5ea5d2c506968fe7;hb=721bca5763a9e2befebc84b37c6d537990d4ce6e;hp=94a12ddeb200e1af805e9056e706b371de6cac79;hpb=060ed82ec24d942c5f519e3dae45e9e2bfb227d8;p=elogind.git diff --git a/src/systemctl.c b/src/systemctl.c index 94a12ddeb..eacc63e94 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -60,7 +60,7 @@ static const char *arg_type = NULL; static char **arg_property = NULL; static bool arg_all = false; -static bool arg_fail = false; +static const char *arg_job_mode = "replace"; static bool arg_user = false; static bool arg_global = false; static bool arg_immediate = false; @@ -76,6 +76,7 @@ static bool arg_full = false; static bool arg_force = false; static bool arg_defaults = false; static bool arg_ask_password = false; +static bool arg_failed = false; static char **arg_wall = NULL; static const char *arg_kill_who = NULL; static const char *arg_kill_mode = NULL; @@ -161,6 +162,7 @@ static void spawn_ask_password_agent(void) { }; int fd; + bool stdout_is_tty, stderr_is_tty; /* Make sure the agent goes away when the parent dies */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) @@ -174,7 +176,10 @@ static void spawn_ask_password_agent(void) { /* Don't leak fds to the agent */ close_all_fds(NULL, 0); - if (!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) { + stdout_is_tty = isatty(STDOUT_FILENO); + stderr_is_tty = isatty(STDERR_FILENO); + + if (!stdout_is_tty || !stderr_is_tty) { /* Detach from stdout/stderr. and reopen * /dev/tty for them. This is important to * ensure that when systemctl is started via @@ -187,15 +192,11 @@ static void spawn_ask_password_agent(void) { _exit(EXIT_FAILURE); } - if (!isatty(STDOUT_FILENO)) { - close(STDOUT_FILENO); + if (!stdout_is_tty) dup2(fd, STDOUT_FILENO); - } - if (!isatty(STDERR_FILENO)) { - close(STDERR_FILENO); + if (!stderr_is_tty) dup2(fd, STDERR_FILENO); - } if (fd > 2) close(fd); @@ -347,9 +348,12 @@ static int compare_unit_info(const void *a, const void *b) { return strcasecmp(u->id, v->id); } -static bool output_show_job(const struct unit_info *u) { +static bool output_show_unit(const struct unit_info *u) { const char *dot; + if (arg_failed) + return streq(u->active_state, "failed"); + return (!arg_type || ((dot = strrchr(u->id, '.')) && streq(dot+1, arg_type))) && (arg_all || !(streq(u->active_state, "inactive") || u->following[0]) || u->job_id > 0); @@ -364,7 +368,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) { job_len = sizeof("JOB")-1; for (u = unit_infos; u < unit_infos + c; u++) { - if (!output_show_job(u)) + if (!output_show_unit(u)) continue; active_len = MAX(active_len, strlen(u->active_state)); @@ -388,7 +392,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) { const char *on_loaded, *off_loaded; const char *on_active, *off_active; - if (!output_show_job(u)) + if (!output_show_unit(u)) continue; n_shown++; @@ -1380,9 +1384,7 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) { mode = (streq(args[0], "isolate") || streq(args[0], "rescue") || - streq(args[0], "emergency")) ? "isolate" : - arg_fail ? "fail" : - "replace"; + streq(args[0], "emergency")) ? "isolate" : arg_job_mode; one_name = table[verb_to_action(args[0])]; @@ -4190,9 +4192,12 @@ static int systemctl_help(void) { " -t --type=TYPE List only units of a particular type\n" " -p --property=NAME Show only properties by this name\n" " -a --all Show all units/properties, including dead/empty ones\n" + " --failed Show only failed units\n" " --full Don't ellipsize unit names on output\n" " --fail When queueing a new job, fail if conflicting jobs are\n" " pending\n" + " --ignore-dependencies\n" + " When queueing a new job, ignore all its dependencies\n" " -q --quiet Suppress output\n" " --no-block Do not wait until operation finished\n" " --no-pager Do not pipe output into a pager.\n" @@ -4330,6 +4335,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { enum { ARG_FAIL = 0x100, + ARG_IGNORE_DEPENDENCIES, ARG_VERSION, ARG_USER, ARG_SYSTEM, @@ -4344,7 +4350,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_DEFAULTS, ARG_KILL_MODE, ARG_KILL_WHO, - ARG_NO_ASK_PASSWORD + ARG_NO_ASK_PASSWORD, + ARG_FAILED }; static const struct option options[] = { @@ -4353,8 +4360,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "type", required_argument, NULL, 't' }, { "property", required_argument, NULL, 'p' }, { "all", no_argument, NULL, 'a' }, + { "failed", no_argument, NULL, ARG_FAILED }, { "full", no_argument, NULL, ARG_FULL }, { "fail", no_argument, NULL, ARG_FAIL }, + { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, { "global", no_argument, NULL, ARG_GLOBAL }, @@ -4421,7 +4430,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) { break; case ARG_FAIL: - arg_fail = true; + arg_job_mode = "fail"; + break; + + case ARG_IGNORE_DEPENDENCIES: + arg_job_mode = "ignore-dependencies"; break; case ARG_USER: @@ -4456,6 +4469,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_full = true; break; + case ARG_FAILED: + arg_failed = true; + break; + case 'q': arg_quiet = true; break; @@ -4651,6 +4668,18 @@ static int parse_time_spec(const char *t, usec_t *_u) { return 0; } +static bool kexec_loaded(void) { + bool loaded = false; + char *s; + + if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) { + if (s[0] == '1') + loaded = true; + free(s); + } + return loaded; +} + static int shutdown_parse_argv(int argc, char *argv[]) { enum { @@ -4688,7 +4717,10 @@ static int shutdown_parse_argv(int argc, char *argv[]) { break; case 'r': - arg_action = ACTION_REBOOT; + if (kexec_loaded()) + arg_action = ACTION_KEXEC; + else + arg_action = ACTION_REBOOT; break; case 'h': @@ -4881,7 +4913,10 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_POWEROFF; return halt_parse_argv(argc, argv); } else if (strstr(program_invocation_short_name, "reboot")) { - arg_action = ACTION_REBOOT; + if (kexec_loaded()) + arg_action = ACTION_KEXEC; + else + arg_action = ACTION_REBOOT; return halt_parse_argv(argc, argv); } else if (strstr(program_invocation_short_name, "shutdown")) { arg_action = ACTION_POWEROFF; @@ -5481,6 +5516,7 @@ int main(int argc, char*argv[]) { case ACTION_HALT: case ACTION_POWEROFF: case ACTION_REBOOT: + case ACTION_KEXEC: r = halt_main(bus); break;