logind-utmp.c revision c2a23db0b91faca3795099fd4b41587bac170ff7
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/***
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright 2015 Daniel Mack
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is free software; you can redistribute it and/or modify it
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen under the terms of the GNU Lesser General Public License as published by
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (at your option) any later version.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is distributed in the hope that it will be useful, but
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Lesser General Public License for more details.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen You should have received a copy of the GNU Lesser General Public License
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen***/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include <errno.h>
7eb08da4b388b920c8a894b1500c9cc7dc1f31efTom Gundersen#include <string.h>
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include <unistd.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <pwd.h>
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "sd-messages.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "strv.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "special.h"
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen#include "unit-name.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "audit.h"
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include "bus-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-error.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "bus-common-errors.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "logind.h"
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen#include "formats-util.h"
c6f7c917a1b494d4455800823472227463f87438Tom Gundersen#include "utmp-wtmp.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering_const_ static usec_t when_wall(usec_t n, usec_t elapse) {
4e731273edfe852a3eee2949cd20f49fd5b4f6d7Lennart Poettering
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier usec_t left;
8fcde01280adcbd07e8205b91ac52b06305b6208Lennart Poettering unsigned int i;
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering static const int wall_timers[] = {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering 25, 40, 55, 70, 100, 130, 150, 180,
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering };
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* If the time is already passed, then don't announce */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (n >= elapse)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen left = elapse - n;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen for (i = 1; i < ELEMENTSOF(wall_timers); i++)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (wall_timers[i] * USEC_PER_MINUTE >= left)
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen return left - wall_timers[i-1] * USEC_PER_MINUTE;
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return left % USEC_PER_HOUR;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmekbool logind_wall_tty_filter(const char *tty, void *userdata) {
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek Manager *m = userdata;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek assert(m);
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek if (!startswith(tty, "/dev/"))
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek return true;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return !streq(tty + 5, m->scheduled_shutdown_tty);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen}
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenstatic int warn_wall(Manager *m, usec_t n) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen char date[FORMAT_TIMESTAMP_MAX] = {};
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen _cleanup_free_ char *l = NULL;
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersen usec_t left;
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersen int r;
43d60b77a83b3185e37c65c4f2649d24c227c7f0Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(m);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (!m->enable_wall_messages)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen left = m->scheduled_shutdown_timeout > n;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen r = asprintf(&l, "%s%sThe system is going down for %s %s%s!",
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen strempty(m->wall_message),
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen isempty(m->wall_message) ? "" : "\n",
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen m->scheduled_shutdown_type,
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen left ? "at " : "NOW",
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen left ? format_timestamp(date, sizeof(date), m->scheduled_shutdown_timeout) : "");
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r < 0) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen log_oom();
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen utmp_wall(l, lookup_uid(m->scheduled_shutdown_uid),
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen m->scheduled_shutdown_tty, logind_wall_tty_filter, m);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 1;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenstatic int wall_message_timeout_handler(
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen sd_event_source *s,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen uint64_t usec,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen void *userdata) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Manager *m = userdata;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen usec_t n, next;
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering int r;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen assert(m);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen assert(s == m->wall_message_timeout_source);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen n = now(CLOCK_REALTIME);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = warn_wall(m, n);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (r == 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen next = when_wall(n, m->scheduled_shutdown_timeout);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (next > 0) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen r = sd_event_source_set_time(s, n + next);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (r < 0)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return log_error_errno(r, "sd_event_source_set_time() failed. %m");
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen if (r < 0)
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return log_error_errno(r, "sd_event_source_set_enabled() failed. %m");
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen }
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen return 0;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen}
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersenint manager_setup_wall_message_timer(Manager *m) {
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen usec_t n, elapse;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen int r;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen assert(m);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen n = now(CLOCK_REALTIME);
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen elapse = m->scheduled_shutdown_timeout;
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* wall message handling */
9a4b012e43f23516373bf398dd9a458439d19939Tom Gundersen
6e37cd2f4af8928d905203108a4331e375d7127cThomas Hindoe Paaboel Andersen if (isempty(m->scheduled_shutdown_type)) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen warn_wall(m, n);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen }
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen if (elapse < n)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* Warn immediately if less than 15 minutes are left */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (elapse - n < 15 * USEC_PER_MINUTE) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen r = warn_wall(m, n);
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek if (r == 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek elapse = when_wall(n, elapse);
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek if (elapse == 0)
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek return 0;
ed88bcfb7c15029f9fc95ee2380759a9eb782d46Zbigniew Jędrzejewski-Szmek
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (m->wall_message_timeout_source) {
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek r = sd_event_source_set_time(m->wall_message_timeout_source, n + elapse);
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek if (r < 0)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen return log_error_errno(r, "sd_event_source_set_time() failed. %m");
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen r = sd_event_source_set_enabled(m->wall_message_timeout_source, SD_EVENT_ONESHOT);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (r < 0)
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return log_error_errno(r, "sd_event_source_set_enabled() failed. %m");
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek } else {
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek r = sd_event_add_time(m->event, &m->wall_message_timeout_source,
e9f3d2d508bfd9fb5b54e82994bda365a71eb864Zbigniew Jędrzejewski-Szmek CLOCK_REALTIME, n + elapse, 0, wall_message_timeout_handler, m);
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek if (r < 0)
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "sd_event_add_time() failed. %m");
ecb08ec6a5c52f2d940f3b8147e2a480affd46e1Zbigniew Jędrzejewski-Szmek }
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek
98a375f6d5cac24eb80d6d4e00699851324afdecTom Gundersen return 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
dab495dc23bf9a5ba0487a057bb594355555a0e9Tom Gundersen