#include "conf-parser.h"
#include "sd-daemon.h"
#include "shutdownd.h"
+#include "exit-status.h"
static const char *arg_type = NULL;
static char **arg_property = NULL;
static bool arg_defaults = false;
static char **arg_wall = NULL;
static usec_t arg_when = 0;
-static bool arg_skip_fsck = false;
-static bool arg_force_fsck = false;
static enum action {
ACTION_INVALID,
ACTION_SYSTEMCTL,
if (isatty(STDOUT_FILENO)) {
- printf("\nLOAD = Load State, reflects whether the unit configuration was properly loaded.\n"
- "ACTIVE = Active State, the high-level unit activation state, i.e. generalization of the substate.\n"
- "SUB = Substate, the low-level unit activation state, possible values depend on unit type.\n"
- "JOB = Job, shows pending jobs for the unit.\n");
+ printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
+ "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
+ "SUB = The low-level unit activation state, values depend on unit type.\n"
+ "JOB = Pending job for the unit.\n");
if (arg_all)
printf("\n%u units listed.\n", c);
pid_t main_pid;
pid_t control_pid;
const char *status_text;
- bool running;
+ bool running:1;
+ bool is_sysv:1;
usec_t start_timestamp;
usec_t exit_timestamp;
printf("\t Exited: %u (%s, code=%s, ", p->pid, strna(t), sigchld_code_to_string(p->code));
free(t);
- if (p->code == CLD_EXITED)
+ if (p->code == CLD_EXITED) {
+ const char *c;
+
printf("status=%i", p->status);
- else
+
+ if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
+ printf("/%s", c);
+
+ } else
printf("signal=%s", signal_to_string(p->status));
printf(")\n");
} else if (i->exit_code > 0) {
printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
- if (i->exit_code == CLD_EXITED)
+ if (i->exit_code == CLD_EXITED) {
+ const char *c;
+
printf("status=%i", i->exit_status);
- else
+
+ if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
+ printf("/%s", c);
+
+ } else
printf("signal=%s", signal_to_string(i->exit_status));
printf(")");
}
i->description = s;
else if (streq(name, "FragmentPath"))
i->path = s;
- else if (streq(name, "SysVPath"))
+ else if (streq(name, "SysVPath")) {
+ i->is_sysv = true;
i->path = s;
- else if (streq(name, "DefaultControlGroup"))
+ } else if (streq(name, "DefaultControlGroup"))
i->default_control_group = s;
else if (streq(name, "StatusText"))
i->status_text = s;
printf("Job %u removed.\n", id);
- } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Unit", "Changed") ||
- dbus_message_is_signal(message, "org.freedesktop.systemd1.Job", "Changed")) {
+ } else if (dbus_message_is_signal(message, "org.freedesktop.DBus.Properties", "PropertiesChanged")) {
const char *path, *interface, *property = "Id";
DBusMessageIter iter, sub;
path = dbus_message_get_path(message);
- interface = dbus_message_get_interface(message);
+
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse message: %s", error.message);
+ goto finish;
+ }
+
+ if (!streq(interface, "org.freedesktop.systemd1.Job") &&
+ !streq(interface, "org.freedesktop.systemd1.Unit"))
+ goto finish;
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
dbus_bus_add_match(bus,
"type='signal',"
"sender='org.freedesktop.systemd1',"
- "interface='org.freedesktop.systemd1.Unit',"
- "member='Changed'",
- &error);
-
- if (dbus_error_is_set(&error)) {
- log_error("Failed to add match: %s", error.message);
- r = -EIO;
- goto finish;
- }
-
- dbus_bus_add_match(bus,
- "type='signal',"
- "sender='org.freedesktop.systemd1',"
- "interface='org.freedesktop.systemd1.Job',"
- "member='Changed'",
+ "interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged'",
&error);
if (dbus_error_is_set(&error)) {
static int shutdown_help(void) {
- printf("%s [OPTIONS...] [now] [WALL...]\n\n"
+ printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
"Shut down the system.\n\n"
" --help Show this help\n"
" -H --halt Halt the machine\n"
" -h Equivalent to --poweroff, overriden by --halt\n"
" -k Don't halt/power-off/reboot, just send warnings\n"
" --no-wall Don't send wall message before halt/power-off/reboot\n"
- " -f Skip fsck on reboot\n"
- " -F Force fsck on reboot\n"
" -c Cancel a pending shutdown\n",
program_invocation_short_name);
return -EINVAL;
n = now(CLOCK_REALTIME);
- s = (time_t) n / USEC_PER_SEC;
+ s = (time_t) (n / USEC_PER_SEC);
+
+ zero(tm);
assert_se(localtime_r(&s, &tm));
tm.tm_hour = (int) hour;
tm.tm_min = (int) minute;
+ tm.tm_sec = 0;
assert_se(s = mktime(&tm));
/* Compatibility nops */
break;
- case 'f':
- arg_skip_fsck = true;
- break;
-
- case 'F':
- arg_force_fsck = true;
- break;
-
case 'c':
arg_action = ACTION_CANCEL_SHUTDOWN;
break;
return r;
}
} else
- arg_when = USEC_PER_MINUTE;
+ arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
/* We skip the time argument */
if (argc > optind + 1)
return -EPERM;
}
- if (arg_force_fsck) {
- if ((r = touch("/forcefsck")) < 0)
- log_warning("Failed to create /forcefsck: %s", strerror(-r));
- } else if (arg_skip_fsck) {
- if ((r = touch("/fastboot")) < 0)
- log_warning("Failed to create /fastboot: %s", strerror(-r));
- }
-
if (arg_when > 0) {
char *m;
+ char date[FORMAT_TIMESTAMP_MAX];
m = strv_join(arg_wall, " ");
r = send_shutdownd(arg_when,
if (r < 0)
log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
- else
+ else {
+ log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
+ format_timestamp(date, sizeof(date), arg_when));
return 0;
+ }
}
if (!arg_dry && !arg_immediate)