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