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