timedatectl.c revision 266f3e269d173f104aa2a5e3ceac9b6979ea5039
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen This file is part of systemd.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Copyright 2012 Lennart Poettering
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Copyright 2013 Kay Sievers
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is free software; you can redistribute it and/or modify it
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen under the terms of the GNU Lesser General Public License as published by
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen the Free Software Foundation; either version 2.1 of the License, or
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (at your option) any later version.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is distributed in the hope that it will be useful, but
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen WITHOUT ANY WARRANTY; without even the implied warranty of
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Lesser General Public License for more details.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen You should have received a copy of the GNU Lesser General Public License
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "spawn-polkit-agent.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic bool arg_no_pager = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic bool arg_ask_password = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic bool arg_adjust_system_clock = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void pager_open_if_enabled(void) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void polkit_agent_open_if_enabled(void) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Open the polkit agent as a child process if necessary */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (arg_transport != BUS_TRANSPORT_LOCAL)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void status_info_clear(StatusInfo *info) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void print_status_info(const StatusInfo *i) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char a[FORMAT_TIMESTAMP_MAX];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *old_tz = NULL, *tz;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Save the old $TZ */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Set the new $TZ */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (setenv("TZ", isempty(i->timezone) ? "UTC" : i->timezone, true) < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sec = (time_t) (i->time / USEC_PER_SEC);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning("Could not get time from timedated and not operating locally, ignoring.");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
b7e7184634d573fb73143210962acce205f37f61Michael Biebl printf(" Local time: %.*s\n", (int) sizeof(a), a);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
b7e7184634d573fb73143210962acce205f37f61Michael Biebl printf(" Universal time: %.*s\n", (int) sizeof(a), a);
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt if (i->rtc_time > 0) {
b7e7184634d573fb73143210962acce205f37f61Michael Biebl rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
b7e7184634d573fb73143210962acce205f37f61Michael Biebl printf(" RTC time: %.*s\n", (int) sizeof(a), a);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl xstrftime(a, "%Z, %z", localtime_r(&sec, &tm));
b7e7184634d573fb73143210962acce205f37f61Michael Biebl /* Restore the $TZ */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf(" Time zone: %s (%.*s)\n"
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen " Network time on: %s\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "NTP synchronized: %s\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " RTC in local TZ: %s\n",
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Warning: The system is configured to read the RTC time in the local time zone.\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " This mode can not be fully supported. It will create various problems\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " with time zone changes and daylight saving time adjustments. The RTC\n"
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen " time is never updated, it relies on external facilities to maintain it.\n"
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen " If at all possible, use RTC in UTC by calling\n"
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen " 'timedatectl set-local-rtc 0'." ANSI_NORMAL "\n", stdout);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int show_status(sd_bus *bus, char **args, unsigned n) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(status_info_clear) StatusInfo info = {};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen static const struct bus_properties_map map[] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "NTP", "b", NULL, offsetof(StatusInfo, ntp_enabled) },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "CanNTP", "b", NULL, offsetof(StatusInfo, ntp_capable) },
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) },
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt { "TimeUSec", "t", NULL, offsetof(StatusInfo, time) },
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "/org/freedesktop/timedate1",
aad0a2c80097926757d4385e5f5492082d47f006Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to query server: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int set_time(sd_bus *bus, char **args, unsigned n) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen bool relative = false, interactive = arg_ask_password;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen polkit_agent_open_if_enabled();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = parse_timestamp(args[1], &t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to parse time specification: %s", args[1]);
d171ed1c50ba64928b7fb30ee2ae729fdfe0826bThomas Hindoe Paaboel Andersen "/org/freedesktop/timedate1",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "xbb", (int64_t)t, relative, interactive);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to set time: %s", bus_error_message(&error, -r));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int set_timezone(sd_bus *bus, char **args, unsigned n) {
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen polkit_agent_open_if_enabled();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "/org/freedesktop/timedate1",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "sb", args[1], arg_ask_password);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to set time zone: %s", bus_error_message(&error, -r));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen polkit_agent_open_if_enabled();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to parse local RTC setting: %s", args[1]);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "/org/freedesktop/timedate1",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "bbb", b, arg_adjust_system_clock, arg_ask_password);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to set local RTC: %s", bus_error_message(&error, -r));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int set_ntp(sd_bus *bus, char **args, unsigned n) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen polkit_agent_open_if_enabled();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to parse NTP setting: %s", args[1]);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "/org/freedesktop/timedate1",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to set ntp: %s", bus_error_message(&error, -r));
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pittstatic int list_timezones(sd_bus *bus, char **args, unsigned n) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to read list of time zones: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void help(void) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s [OPTIONS...] COMMAND ...\n\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "Query or change system time and date settings.\n\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " -h --help Show this help message\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " --version Show package version\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " --no-pager Do not pipe output into a pager\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " --no-ask-password Do not prompt for password\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " -H --host=[USER@]HOST Operate on remote host\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " -M --machine=CONTAINER Operate on local container\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " --adjust-system-clock Adjust system clock when changing local RTC mode\n\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " status Show current time settings\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " set-time TIME Set system time\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " set-timezone ZONE Set system time zone\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " list-timezones Show known time zones\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " set-local-rtc BOOL Control whether RTC is in local time\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen " set-ntp BOOL Enable or disable network time synchronization\n",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen program_invocation_short_name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int parse_argv(int argc, char *argv[]) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen static const struct option options[] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "help", no_argument, NULL, 'h' },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "version", no_argument, NULL, ARG_VERSION },
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt { "no-pager", no_argument, NULL, ARG_NO_PAGER },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "machine", required_argument, NULL, 'M' },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen arg_transport = BUS_TRANSPORT_REMOTE;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen arg_transport = BUS_TRANSPORT_MACHINE;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case ARG_ADJUST_SYSTEM_CLOCK:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen arg_adjust_system_clock = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_not_reached("Unhandled option");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen static const struct {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "status", LESS, 1, show_status },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "set-time", EQUAL, 2, set_time },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "set-timezone", EQUAL, 2, set_timezone },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "list-timezones", EQUAL, 1, list_timezones },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "set-local-rtc", EQUAL, 2, set_local_rtc },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen { "set-ntp", EQUAL, 2, set_ntp, },
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Special rule: no arguments means "status" */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (streq(argv[optind], "help")) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen for (i = 0; i < ELEMENTSOF(verbs); i++)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (streq(argv[optind], verbs[i].verb))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i >= ELEMENTSOF(verbs)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Unknown operation %s", argv[optind]);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Invalid number of arguments.");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Too few arguments.");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Too many arguments.");
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek assert_not_reached("Unknown comparison operator.");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return verbs[i].dispatch(bus, argv + optind, left);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint main(int argc, char *argv[]) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = bus_connect_transport(arg_transport, arg_host, false, &bus);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl log_error_errno(r, "Failed to create bus connection: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = timedatectl_main(bus, argc, argv);