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