From 08e4b1c5c8aeb52e806b7cf994173660190e61ab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Aug 2010 22:40:11 +0200 Subject: [PATCH] shutdown: various fixes for handling of delayed shutdowns --- src/shutdownd.c | 36 ++++++++++++++++++++++++------------ src/systemctl.c | 15 +++++++++++---- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/shutdownd.c b/src/shutdownd.c index 80ff2e9fb..59439bca8 100644 --- a/src/shutdownd.c +++ b/src/shutdownd.c @@ -99,30 +99,31 @@ static int read_packet(int fd, struct shutdownd_command *_c) { return 1; } -static void warn_wall(struct shutdownd_command *c) { +static void warn_wall(usec_t n, struct shutdownd_command *c) { assert(c); assert(c->warn_wall); + if (n >= c->elapse) + return; + if (c->wall_message[0]) utmp_wall(c->wall_message); else { char date[FORMAT_TIMESTAMP_MAX]; const char* prefix; - char *l; + char *l = NULL; if (c->mode == 'H') - prefix = "The system is going down for system halt at"; + prefix = "The system is going down for system halt at "; else if (c->mode == 'P') - prefix = "The system is going down for power-off at"; + prefix = "The system is going down for power-off at "; else if (c->mode == 'r') - prefix = "The system is going down for reboot at"; + prefix = "The system is going down for reboot at "; else assert_not_reached("Unknown mode!"); - if (asprintf(&l, "%s %s!", - prefix, - format_timestamp(date, sizeof(date), c->elapse)) < 0) + if (asprintf(&l, "%s%s!", prefix, format_timestamp(date, sizeof(date), c->elapse)) < 0) log_error("Failed to allocate wall message"); else { utmp_wall(l); @@ -151,8 +152,10 @@ static usec_t when_wall(usec_t n, usec_t elapse) { left = elapse - n; for (i = 0; i < ELEMENTSOF(table); i++) - if (n + table[i].delay >= elapse) + if (n + table[i].delay >= elapse) { sub = ((left / table[i].interval) * table[i].interval); + break; + } if (i >= ELEMENTSOF(table)) sub = ((left / USEC_PER_HOUR) * USEC_PER_HOUR); @@ -272,7 +275,7 @@ int main(int argc, char *argv[]) { /* Warn immediately if less than 15 minutes are left */ if (n < c.elapse && n + 15*USEC_PER_MINUTE >= c.elapse) - warn_wall(&c); + warn_wall(n, &c); } /* Disallow logins 5 minutes prior to shutdown */ @@ -300,7 +303,7 @@ int main(int argc, char *argv[]) { if (pollfd[FD_WALL_TIMER].revents) { struct itimerspec its; - warn_wall(&c); + warn_wall(n, &c); flush_fd(pollfd[FD_WALL_TIMER].fd); /* Restart timer */ @@ -315,6 +318,8 @@ int main(int argc, char *argv[]) { if (pollfd[FD_NOLOGIN_TIMER].revents) { int e; + log_info("Creating /etc/nologin, blocking further logins..."); + if ((e = touch("/etc/nologin")) < 0) log_error("Failed to create /etc/nologin: %s", strerror(-e)); else @@ -347,7 +352,14 @@ finish: sw[1] = c.mode; sw[2] = 0; - execl(SYSTEMCTL_BINARY_PATH, "shutdown", sw, "now", NULL); + execl(SYSTEMCTL_BINARY_PATH, + "shutdown", + sw, + "now", + (c.warn_wall && c.wall_message[0]) ? c.wall_message : + (c.warn_wall ? NULL : "--no-wall"), + NULL); + log_error("Failed to execute /sbin/shutdown: %m"); } diff --git a/src/systemctl.c b/src/systemctl.c index 50473a182..44b884800 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -3829,7 +3829,7 @@ static int halt_help(void) { 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" @@ -4137,11 +4137,14 @@ static int parse_time_spec(const char *t, usec_t *_u) { 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)); @@ -4239,7 +4242,7 @@ static int shutdown_parse_argv(int argc, char *argv[]) { 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) @@ -4819,6 +4822,7 @@ static int halt_main(DBusConnection *bus) { if (arg_when > 0) { char *m; + char date[FORMAT_TIMESTAMP_MAX]; m = strv_join(arg_wall, " "); r = send_shutdownd(arg_when, @@ -4831,8 +4835,11 @@ static int halt_main(DBusConnection *bus) { 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) -- 2.30.2