timedatectl.c revision ab59f4123a6f9c32953e522cc9afc5fc610d59ca
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2012 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2013 Kay Sievers
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <stdlib.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <stdbool.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <getopt.h>
50f1e641a93cacfc693b0c3d300bee5df0c8c460Tom Gundersen#include <locale.h>
71d35b6b5563817dfbe757ab9e3b9f018b2db491Thomas Hindoe Paaboel Andersen
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering#include "sd-bus.h"
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering#include "bus-util.h"
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering#include "bus-error.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "spawn-polkit-agent.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "build.h"
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering#include "strv.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "pager.h"
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering#include "terminal-util.h"
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poetteringstatic bool arg_no_pager = false;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poetteringstatic bool arg_ask_password = true;
23502de3b0891455c8ce499a9eb61b69d060a829Daniel Mackstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
23502de3b0891455c8ce499a9eb61b69d060a829Daniel Mackstatic char *arg_host = NULL;
23502de3b0891455c8ce499a9eb61b69d060a829Daniel Mackstatic bool arg_adjust_system_clock = false;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poetteringstatic void pager_open_if_enabled(void) {
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering if (arg_no_pager)
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering return;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering pager_open(false);
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering}
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poetteringstatic void polkit_agent_open_if_enabled(void) {
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
6f717d0817573a76c3e586eae02793d8b23a0581Lennart Poettering /* Open the polkit agent as a child process if necessary */
6f717d0817573a76c3e586eae02793d8b23a0581Lennart Poettering if (!arg_ask_password)
6f717d0817573a76c3e586eae02793d8b23a0581Lennart Poettering return;
e0240c64b76ba8f0c9219feb23a5783f23100216Lennart Poettering
e0240c64b76ba8f0c9219feb23a5783f23100216Lennart Poettering if (arg_transport != BUS_TRANSPORT_LOCAL)
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering return;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering polkit_agent_open();
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering}
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poetteringtypedef struct StatusInfo {
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering usec_t time;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering char *timezone;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering usec_t rtc_time;
6f717d0817573a76c3e586eae02793d8b23a0581Lennart Poettering bool rtc_local;
6f717d0817573a76c3e586eae02793d8b23a0581Lennart Poettering
6f717d0817573a76c3e586eae02793d8b23a0581Lennart Poettering bool ntp_enabled;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering bool ntp_capable;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering bool ntp_synced;
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering} StatusInfo;
d15ad74251454d55b715958d8e6f50f45195904aLennart Poettering
d15ad74251454d55b715958d8e6f50f45195904aLennart Poetteringstatic void status_info_clear(StatusInfo *info) {
d15ad74251454d55b715958d8e6f50f45195904aLennart Poettering if (info) {
d15ad74251454d55b715958d8e6f50f45195904aLennart Poettering free(info->timezone);
d15ad74251454d55b715958d8e6f50f45195904aLennart Poettering zero(*info);
d15ad74251454d55b715958d8e6f50f45195904aLennart Poettering }
d15ad74251454d55b715958d8e6f50f45195904aLennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic void print_status_info(const StatusInfo *i) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering char a[FORMAT_TIMESTAMP_MAX];
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering struct tm tm;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering time_t sec;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bool have_time = false;
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering const char *old_tz = NULL, *tz;
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering int r;
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering assert(i);
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering /* Save the old $TZ */
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering tz = getenv("TZ");
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering if (tz)
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering old_tz = strdupa(tz);
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering /* Set the new $TZ */
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering if (setenv("TZ", i->timezone, true) < 0)
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m");
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering else
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering tzset();
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering if (i->time != 0) {
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering sec = (time_t) (i->time / USEC_PER_SEC);
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering have_time = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sec = time(NULL);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering have_time = true;
7b50eb2efa122200e39646c19a29abab302f7d24Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Could not get time from timedated and not operating locally, ignoring.");
ee3d6aff9bd73c1b23e29d1fa1fa6f7a1ef0533bLennart Poettering
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering if (have_time) {
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering printf(" Local time: %.*s\n", (int) sizeof(a), a);
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering printf(" Universal time: %.*s\n", (int) sizeof(a), a);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering printf(" Local time: %s\n", "n/a");
f5430a3ef308f3a102899fcaf7fbece757082f2aLennart Poettering printf(" Universal time: %s\n", "n/a");
d75acfb059ece4512278b8820a9103664996f1e5Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (i->rtc_time > 0) {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering time_t rtc_sec;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering printf(" RTC time: %.*s\n", (int) sizeof(a), a);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering printf(" RTC time: %s\n", "n/a");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poettering if (have_time)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering xstrftime(a, "%Z, %z", localtime_r(&sec, &tm));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Restore the $TZ */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (old_tz)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = setenv("TZ", old_tz, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek r = unsetenv("TZ");
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering if (r < 0)
c0eb11cfd016381fe02875a4ef29c1ade00c94e7Lennart Poettering log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering tzset();
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering printf(" Time zone: %s (%.*s)\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " Network time on: %s\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "NTP synchronized: %s\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " RTC in local TZ: %s\n",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a",
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering yes_no(i->ntp_synced),
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering yes_no(i->rtc_local));
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (i->rtc_local)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering fputs("\n" ANSI_HIGHLIGHT_ON
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering "Warning: The system is configured to read the RTC time in the local time zone.\n"
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering " This mode can not be fully supported. It will create various problems\n"
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering " with time zone changes and daylight saving time adjustments. The RTC\n"
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering " time is never updated, it relies on external facilities to maintain it.\n"
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek " If at all possible, use RTC in UTC by calling\n"
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek " 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek}
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmekstatic int show_status(sd_bus *bus, char **args, unsigned n) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek _cleanup_(status_info_clear) StatusInfo info = {};
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering static const struct bus_properties_map map[] = {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) },
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) },
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek { "NTP", "b", NULL, offsetof(StatusInfo, ntp_enabled) },
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek { "CanNTP", "b", NULL, offsetof(StatusInfo, ntp_capable) },
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) },
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek { "TimeUSec", "t", NULL, offsetof(StatusInfo, time) },
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) },
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek {}
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek };
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering int r;
549c1a2564b56f2bb38f1203d59c747ea15817f3Tom Gundersen
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering assert(bus);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering r = bus_map_all_properties(bus,
549c1a2564b56f2bb38f1203d59c747ea15817f3Tom Gundersen "org.freedesktop.timedate1",
549c1a2564b56f2bb38f1203d59c747ea15817f3Tom Gundersen "/org/freedesktop/timedate1",
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering map,
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek &info);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek if (r < 0)
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to query server: %m");
f91dc2400dc33e9a0745ecaaef7489af116dca38Lennart Poettering
f91dc2400dc33e9a0745ecaaef7489af116dca38Lennart Poettering print_status_info(&info);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek return r;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek}
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmekstatic int set_time(sd_bus *bus, char **args, unsigned n) {
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek bool relative = false, interactive = arg_ask_password;
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek usec_t t;
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek int r;
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek assert(args);
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek assert(n == 2);
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek polkit_agent_open_if_enabled();
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek r = parse_timestamp(args[1], &t);
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek if (r < 0) {
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek log_error("Failed to parse time specification: %s", args[1]);
50f1e641a93cacfc693b0c3d300bee5df0c8c460Tom Gundersen return r;
9ead3519c54b6d1b79b35541873b5cf7c8b3a7d3Lennart Poettering }
50f1e641a93cacfc693b0c3d300bee5df0c8c460Tom Gundersen
50f1e641a93cacfc693b0c3d300bee5df0c8c460Tom Gundersen r = sd_bus_call_method(bus,
50f1e641a93cacfc693b0c3d300bee5df0c8c460Tom Gundersen "org.freedesktop.timedate1",
50f1e641a93cacfc693b0c3d300bee5df0c8c460Tom Gundersen "/org/freedesktop/timedate1",
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen "org.freedesktop.timedate1",
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering "SetTime",
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering &error,
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering NULL,
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering "xbb", (int64_t)t, relative, interactive);
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering if (r < 0)
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering log_error("Failed to set time: %s", bus_error_message(&error, -r));
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering return r;
6af47493de0ef2b66d4c3fbcdd4a2e12fec4bfbaLennart Poettering}
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersenstatic int set_timezone(sd_bus *bus, char **args, unsigned n) {
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen int r;
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen assert(args);
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen assert(n == 2);
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen polkit_agent_open_if_enabled();
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_call_method(bus,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "org.freedesktop.timedate1",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "/org/freedesktop/timedate1",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "org.freedesktop.timedate1",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "SetTimezone",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering &error,
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering NULL,
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "sb", args[1], arg_ask_password);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_error("Failed to set time zone: %s", bus_error_message(&error, -r));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
36d9205d669bcdcb04fa730d1f3549a9fc9a9001Tom Gundersenstatic int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r, b;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(args);
28b9b7640603f88cb49f95609331fa5072715f15Lennart Poettering assert(n == 2);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
105e151299dc1208855380be2b22d0db2d66ebc6Lennart Poettering polkit_agent_open_if_enabled();
5d27351f8546530cf779847b0b04b0172c09f9d0Tom Gundersen
547973dea7abd6c124ff6c79fe2bbe322a7314aeLennart Poettering b = parse_boolean(args[1]);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (b < 0) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_error("Failed to parse local RTC setting: %s", args[1]);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return b;
7778dffff3d8bd7438fe19a248c16203668324c9Daniel Mack }
7778dffff3d8bd7438fe19a248c16203668324c9Daniel Mack
7778dffff3d8bd7438fe19a248c16203668324c9Daniel Mack r = sd_bus_call_method(bus,
7778dffff3d8bd7438fe19a248c16203668324c9Daniel Mack "org.freedesktop.timedate1",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "/org/freedesktop/timedate1",
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering "org.freedesktop.timedate1",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "SetLocalRTC",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering &error,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering NULL,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering "bbb", b, arg_adjust_system_clock, arg_ask_password);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
7b50eb2efa122200e39646c19a29abab302f7d24Lennart Poettering log_error("Failed to set local RTC: %s", bus_error_message(&error, -r));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return r;
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering}
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poetteringstatic int set_ntp(sd_bus *bus, char **args, unsigned n) {
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poettering int b, r;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering assert(args);
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering assert(n == 2);
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering polkit_agent_open_if_enabled();
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poettering b = parse_boolean(args[1]);
if (b < 0) {
log_error("Failed to parse NTP setting: %s", args[1]);
return b;
}
r = sd_bus_call_method(bus,
"org.freedesktop.timedate1",
"/org/freedesktop/timedate1",
"org.freedesktop.timedate1",
"SetNTP",
&error,
NULL,
"bb", b, arg_ask_password);
if (r < 0)
log_error("Failed to set ntp: %s", bus_error_message(&error, -r));
return r;
}
static int list_timezones(sd_bus *bus, char **args, unsigned n) {
_cleanup_strv_free_ char **zones = NULL;
int r;
assert(args);
assert(n == 1);
r = get_timezones(&zones);
if (r < 0)
return log_error_errno(r, "Failed to read list of time zones: %m");
pager_open_if_enabled();
strv_print(zones);
return 0;
}
static void help(void) {
printf("%s [OPTIONS...] COMMAND ...\n\n"
"Query or change system time and date settings.\n\n"
" -h --help Show this help message\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" --no-ask-password Do not prompt for password\n"
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
" --adjust-system-clock Adjust system clock when changing local RTC mode\n\n"
"Commands:\n"
" status Show current time settings\n"
" set-time TIME Set system time\n"
" set-timezone ZONE Set system time zone\n"
" list-timezones Show known time zones\n"
" set-local-rtc BOOL Control whether RTC is in local time\n"
" set-ntp BOOL Enable or disable network time synchronization\n",
program_invocation_short_name);
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_NO_PAGER,
ARG_ADJUST_SYSTEM_CLOCK,
ARG_NO_ASK_PASSWORD
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "host", required_argument, NULL, 'H' },
{ "machine", required_argument, NULL, 'M' },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{ "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK },
{}
};
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0)
switch (c) {
case 'h':
help();
return 0;
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0;
case 'H':
arg_transport = BUS_TRANSPORT_REMOTE;
arg_host = optarg;
break;
case 'M':
arg_transport = BUS_TRANSPORT_MACHINE;
arg_host = optarg;
break;
case ARG_NO_ASK_PASSWORD:
arg_ask_password = false;
break;
case ARG_ADJUST_SYSTEM_CLOCK:
arg_adjust_system_clock = true;
break;
case ARG_NO_PAGER:
arg_no_pager = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
return 1;
}
static int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
static const struct {
const char* verb;
const enum {
MORE,
LESS,
EQUAL
} argc_cmp;
const int argc;
int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
} verbs[] = {
{ "status", LESS, 1, show_status },
{ "set-time", EQUAL, 2, set_time },
{ "set-timezone", EQUAL, 2, set_timezone },
{ "list-timezones", EQUAL, 1, list_timezones },
{ "set-local-rtc", EQUAL, 2, set_local_rtc },
{ "set-ntp", EQUAL, 2, set_ntp, },
};
int left;
unsigned i;
assert(argc >= 0);
assert(argv);
left = argc - optind;
if (left <= 0)
/* Special rule: no arguments means "status" */
i = 0;
else {
if (streq(argv[optind], "help")) {
help();
return 0;
}
for (i = 0; i < ELEMENTSOF(verbs); i++)
if (streq(argv[optind], verbs[i].verb))
break;
if (i >= ELEMENTSOF(verbs)) {
log_error("Unknown operation %s", argv[optind]);
return -EINVAL;
}
}
switch (verbs[i].argc_cmp) {
case EQUAL:
if (left != verbs[i].argc) {
log_error("Invalid number of arguments.");
return -EINVAL;
}
break;
case MORE:
if (left < verbs[i].argc) {
log_error("Too few arguments.");
return -EINVAL;
}
break;
case LESS:
if (left > verbs[i].argc) {
log_error("Too many arguments.");
return -EINVAL;
}
break;
default:
assert_not_reached("Unknown comparison operator.");
}
return verbs[i].dispatch(bus, argv + optind, left);
}
int main(int argc, char *argv[]) {
_cleanup_bus_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = bus_open_transport(arg_transport, arg_host, false, &bus);
if (r < 0) {
log_error_errno(r, "Failed to create bus connection: %m");
goto finish;
}
r = timedatectl_main(bus, argc, argv);
finish:
pager_close();
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}