X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshutdownd.c;h=0ffa8b28815f4c1805b14e16c77cc7853609f272;hp=80ff2e9fba9b577842ae38ee51639d40dc93cb0f;hb=72b9ed828bd22f3ddd74b6853c183eebf006d6d8;hpb=2396fb04f78eaa9842c747e384218f0069446960 diff --git a/src/shutdownd.c b/src/shutdownd.c index 80ff2e9fb..0ffa8b288 100644 --- a/src/shutdownd.c +++ b/src/shutdownd.c @@ -99,35 +99,32 @@ 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) { + char date[FORMAT_TIMESTAMP_MAX]; + const char *prefix; + char *l = NULL; assert(c); assert(c->warn_wall); - if (c->wall_message[0]) - utmp_wall(c->wall_message); + if (n >= c->elapse) + return; + + if (c->mode == 'H') + 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 "; + else if (c->mode == 'r') + prefix = "The system is going down for reboot at "; + else + assert_not_reached("Unknown mode!"); + + if (asprintf(&l, "%s%s%s%s!", c->wall_message, c->wall_message[0] ? "\n" : "", + prefix, format_timestamp(date, sizeof(date), c->elapse)) < 0) + log_error("Failed to allocate wall message"); else { - char date[FORMAT_TIMESTAMP_MAX]; - const char* prefix; - char *l; - - if (c->mode == 'H') - 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"; - else if (c->mode == 'r') - 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) - log_error("Failed to allocate wall message"); - else { - utmp_wall(l); - free(l); - } + utmp_wall(l, NULL); + free(l); } } @@ -151,8 +148,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); @@ -173,7 +172,7 @@ int main(int argc, char *argv[]) { _FD_MAX }; - int r = 4, n_fds; + int r = EXIT_FAILURE, n_fds; int one = 1; struct shutdownd_command c; struct pollfd pollfd[_FD_MAX]; @@ -182,31 +181,33 @@ int main(int argc, char *argv[]) { if (getppid() != 1) { log_error("This program should be invoked by init only."); - return 1; + return EXIT_FAILURE; } if (argc > 1) { log_error("This program does not take arguments."); - return 1; + return EXIT_FAILURE; } log_set_target(LOG_TARGET_SYSLOG_OR_KMSG); log_parse_environment(); log_open(); + umask(0022); + if ((n_fds = sd_listen_fds(true)) < 0) { log_error("Failed to read listening file descriptors from environment: %s", strerror(-r)); - return 1; + return EXIT_FAILURE; } if (n_fds != 1) { log_error("Need exactly one file descriptor."); - return 2; + return EXIT_FAILURE; } if (setsockopt(SD_LISTEN_FDS_START, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) { log_error("SO_PASSCRED failed: %m"); - return 3; + return EXIT_FAILURE; } zero(c); @@ -224,7 +225,7 @@ int main(int argc, char *argv[]) { if ((pollfd[i].fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) { log_error("timerfd_create(): %m"); - failed = false; + failed = true; } } @@ -272,7 +273,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 +301,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,8 +316,10 @@ int main(int argc, char *argv[]) { if (pollfd[FD_NOLOGIN_TIMER].revents) { int e; - if ((e = touch("/etc/nologin")) < 0) - log_error("Failed to create /etc/nologin: %s", strerror(-e)); + log_info("Creating /run/nologin, blocking further logins..."); + + if ((e = write_one_line_file_atomic("/run/nologin", "System is going down.")) < 0) + log_error("Failed to create /run/nologin: %s", strerror(-e)); else unlink_nologin = true; @@ -330,7 +333,7 @@ int main(int argc, char *argv[]) { } while (c.elapse > 0); - r = 0; + r = EXIT_SUCCESS; log_debug("systemd-shutdownd stopped as pid %lu", (unsigned long) getpid()); @@ -340,20 +343,27 @@ finish: if (pollfd[i].fd >= 0) close_nointr_nofail(pollfd[i].fd); - if (exec_shutdown) { + if (unlink_nologin) + unlink("/run/nologin"); + + if (exec_shutdown && !c.dry_run) { char sw[3]; sw[0] = '-'; 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"); } - if (unlink_nologin) - unlink("/etc/nologin"); - sd_notify(false, "STATUS=Exiting...");