shutdownd.c revision 4cfa2c999dea269ddc646bfeba6c7f1021a73843
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/***
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2010 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering***/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/socket.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/poll.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/types.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/timerfd.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <assert.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <string.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <errno.h>
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#include <unistd.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <fcntl.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <systemd/sd-daemon.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "shutdownd.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "log.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "macro.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "util.h"
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek#include "utmp-wtmp.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int read_packet(int fd, struct shutdownd_command *_c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct msghdr msghdr;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct iovec iovec;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek struct ucred *ucred;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering union {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct cmsghdr cmsghdr;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } control;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct shutdownd_command c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ssize_t n;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(fd >= 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(_c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(iovec);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering iovec.iov_base = &c;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering iovec.iov_len = sizeof(c);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(control);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(msghdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering msghdr.msg_iov = &iovec;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering msghdr.msg_iovlen = 1;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering msghdr.msg_control = &control;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering msghdr.msg_controllen = sizeof(control);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((n = recvmsg(fd, &msghdr, MSG_DONTWAIT)) <= 0) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (n >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Short read");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -EIO;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (errno == EAGAIN || errno == EINTR)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("recvmsg(): %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -errno;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering control.cmsghdr.cmsg_level != SOL_SOCKET ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Received message without credentials. Ignoring.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (ucred->uid != 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Got request from unprivileged user. Ignoring.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n != sizeof(c)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("Message has invalid size. Ignoring");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char_array_0(c.wall_message);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *_c = c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 1;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void warn_wall(usec_t n, struct shutdownd_command *c) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char date[FORMAT_TIMESTAMP_MAX];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *prefix;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *l = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(c->warn_wall);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n >= c->elapse)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (c->mode == 'H')
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix = "The system is going down for system halt at ";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (c->mode == 'P')
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix = "The system is going down for power-off at ";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (c->mode == 'r')
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix = "The system is going down for reboot at ";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_not_reached("Unknown mode!");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (asprintf(&l, "%s%s%s%s!", c->wall_message, c->wall_message[0] ? "\n" : "",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, format_timestamp(date, sizeof(date), c->elapse)) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to allocate wall message");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering utmp_wall(l, NULL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek free(l);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poetteringstatic usec_t when_wall(usec_t n, usec_t elapse) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering static const struct {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t delay;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek usec_t interval;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek } table[] = {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { 10 * USEC_PER_MINUTE, USEC_PER_MINUTE },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { USEC_PER_HOUR, 15 * USEC_PER_MINUTE },
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering { 3 * USEC_PER_HOUR, 30 * USEC_PER_MINUTE }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering };
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering usec_t left, sub;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned i;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek /* If the time is already passed, then don't announce */
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (n >= elapse)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return 0;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek left = elapse - n;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek for (i = 0; i < ELEMENTSOF(table); i++)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (n + table[i].delay >= elapse) {
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek sub = ((left / table[i].interval) * table[i].interval);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek break;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (i >= ELEMENTSOF(table))
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek sub = ((left / USEC_PER_HOUR) * USEC_PER_HOUR);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return elapse > sub ? elapse - sub : 1;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic usec_t when_nologin(usec_t elapse) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return elapse > 5*USEC_PER_MINUTE ? elapse - 5*USEC_PER_MINUTE : 1;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekint main(int argc, char *argv[]) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering enum {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FD_SOCKET,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FD_WALL_TIMER,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering FD_NOLOGIN_TIMER,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek FD_SHUTDOWN_TIMER,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _FD_MAX
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering };
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r = EXIT_FAILURE, n_fds;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct shutdownd_command c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct pollfd pollfd[_FD_MAX];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool exec_shutdown = false, unlink_nologin = false, failed = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (getppid() != 1) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("This program should be invoked by init only.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return EXIT_FAILURE;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (argc > 1) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek log_error("This program does not take arguments.");
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return EXIT_FAILURE;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_set_target(LOG_TARGET_AUTO);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_parse_environment();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_open();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering umask(0022);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((n_fds = sd_listen_fds(true)) < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to read listening file descriptors from environment: %s", strerror(-r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return EXIT_FAILURE;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n_fds != 1) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Need exactly one file descriptor.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return EXIT_FAILURE;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(pollfd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pollfd[FD_SOCKET].fd = SD_LISTEN_FDS_START;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pollfd[FD_SOCKET].events = POLLIN;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d3b6d0c21ea5a0d15ec6dbd8b8d179138b7463bcZbigniew Jędrzejewski-Szmek for (i = 0; i < _FD_MAX; i++) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (i == FD_SOCKET)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pollfd[i].events = POLLIN;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((pollfd[i].fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek log_error("timerfd_create(): %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering failed = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (failed)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto finish;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek log_debug("systemd-shutdownd running as pid %lu", (unsigned long) getpid());
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_notify(false,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "READY=1\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "STATUS=Processing requests...");
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering do {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int k;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek usec_t n;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (poll(pollfd, _FD_MAX, -1) < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (errno == EAGAIN || errno == EINTR)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("poll(): %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto finish;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n = now(CLOCK_REALTIME);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (pollfd[FD_SOCKET].revents) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((k = read_packet(pollfd[FD_SOCKET].fd, &c)) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto finish;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (k > 0 && c.elapse > 0) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek struct itimerspec its;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek char date[FORMAT_TIMESTAMP_MAX];
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (c.warn_wall) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek /* Send wall messages every so often */
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek zero(its);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek timespec_store(&its.it_value, when_wall(n, c.elapse));
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek log_error("timerfd_settime(): %m");
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek goto finish;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Warn immediately if less than 15 minutes are left */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (n < c.elapse &&
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n + 15*USEC_PER_MINUTE >= c.elapse)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering warn_wall(n, &c);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Disallow logins 5 minutes prior to shutdown */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(its);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering timespec_store(&its.it_value, when_nologin(c.elapse));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (timerfd_settime(pollfd[FD_NOLOGIN_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("timerfd_settime(): %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto finish;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Shutdown after the specified time is reached */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(its);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering timespec_store(&its.it_value, c.elapse);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (timerfd_settime(pollfd[FD_SHUTDOWN_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("timerfd_settime(): %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto finish;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_notifyf(false,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "STATUS=Shutting down at %s...",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering format_timestamp(date, sizeof(date), c.elapse));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (pollfd[FD_WALL_TIMER].revents) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct itimerspec its;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering warn_wall(n, &c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering flush_fd(pollfd[FD_WALL_TIMER].fd);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Restart timer */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering zero(its);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering timespec_store(&its.it_value, when_wall(n, c.elapse));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (timerfd_settime(pollfd[FD_WALL_TIMER].fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("timerfd_settime(): %m");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering goto finish;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (pollfd[FD_NOLOGIN_TIMER].revents) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int e;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("Creating /run/nologin, blocking further logins...");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if ((e = write_one_line_file_atomic("/run/nologin", "System is going down.")) < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_error("Failed to create /run/nologin: %s", strerror(-e));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek unlink_nologin = true;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer flush_fd(pollfd[FD_NOLOGIN_TIMER].fd);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (pollfd[FD_SHUTDOWN_TIMER].revents) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek exec_shutdown = true;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek goto finish;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek } while (c.elapse > 0);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = EXIT_SUCCESS;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_debug("systemd-shutdownd stopped as pid %lu", (unsigned long) getpid());
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekfinish:
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek for (i = 0; i < _FD_MAX; i++)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (pollfd[i].fd >= 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek close_nointr_nofail(pollfd[i].fd);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (unlink_nologin)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek unlink("/run/nologin");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (exec_shutdown && !c.dry_run) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek char sw[3];
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sw[0] = '-';
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sw[1] = c.mode;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sw[2] = 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek execl(SYSTEMCTL_BINARY_PATH,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "shutdown",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sw,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "now",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek (c.warn_wall && c.wall_message[0]) ? c.wall_message :
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek (c.warn_wall ? NULL : "--no-wall"),
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek NULL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_error("Failed to execute /sbin/shutdown: %m");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sd_notify(false,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "STATUS=Exiting...");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek